#pragma once
#include"string/rolling-hash-base.hpp"structRollingHashValue:RollingHashBase{u64hash,power;RollingHashValue():hash(0),power(1){}RollingHashValue(u64h,u64p):hash(h),power(p){}template<classT>staticRollingHashValuesingle(Tv){returnRollingHashValue(normalize(v),base);}RollingHashValue&operator+=(RollingHashValuerhs){hash=add(mul(hash,rhs.power),rhs.hash);power=mul(power,rhs.power);return*this;}friendRollingHashValueoperator+(RollingHashValuelhs,RollingHashValuerhs){returnlhs+=rhs;}friendbooloperator==(RollingHashValuelhs,RollingHashValuerhs){returnlhs.hash==rhs.hash&&lhs.power==rhs.power;}};structRollingHashValueReversible:RollingHashBase{u64hash,reverse_hash,power;RollingHashValueReversible():hash(0),reverse_hash(0),power(1){}RollingHashValueReversible(u64h,u64rh,u64p):hash(h),reverse_hash(rh),power(p){}template<classT>staticRollingHashValueReversiblesingle(Tv){u64h=normalize(v);returnRollingHashValueReversible(h,h,base);}RollingHashValueReversible&operator+=(RollingHashValueReversiblerhs){hash=add(mul(hash,rhs.power),rhs.hash);reverse_hash=add(reverse_hash,mul(rhs.reverse_hash,power));power=mul(power,rhs.power);return*this;}RollingHashValueReversiblereversed()const{returnRollingHashValueReversible(reverse_hash,hash,power);}friendRollingHashValueReversibleoperator+(RollingHashValueReversiblelhs,RollingHashValueReversiblerhs){returnlhs+=rhs;}friendbooloperator==(RollingHashValueReversiblelhs,RollingHashValueReversiblerhs){returnlhs.hash==rhs.hash&&lhs.reverse_hash==rhs.reverse_hash&&lhs.power==rhs.power;}};