#ifndef AFSTR_HASHED_STRING
#define AFSTR_HASHED_STRING
#include<algorithm>
#include<vector>template<intmod,intseed>structSingleHash{intn;std::vector<int>pow,h;SingleHash(void)=default;SingleHash(std::string&s){init(s);}inlinevoidinit(std::string&s){n=s.size(),h.assign(n+2,0),pow.assign(n+2,1);for(inti=1;i<=n;i++){pow[i]=1ll*pow[i-1]*seed%mod;h[i]=(1ll*h[i-1]*seed+s[i-1])%mod;}}inlineintget_hash(intl,intr){return(h[r+1]-1ll*h[l]*pow[r-l+1]%mod+mod)%mod;}inlineboolcheck_same(intl1,intr1,intl2,intr2){returnget_hash(l1,r1)==get_hash(l2,r2);}};structHashedString{SingleHash<998244353,477>H1;SingleHash<1000000007,233>H2;HashedString(void)=default;HashedString(std::strings):H1(s),H2(s){}inlinevoidinit(std::strings){H1.init(s),H2.init(s);}std::pair<int,int>get_hash(intl,intr){// not recommended.return{H1.get_hash(l,r),H2.get_hash(l,r)};}// caution: index begins with zero.// If index beginning with one is wanted, use s = ' ' + sinlineboolcheck_same(intl1,intr1,intl2,intr2){returnH1.check_same(l1,r1,l2,r2)&&H2.check_same(l1,r1,l2,r2);}inlineboolcheck_period(intl,intr,intp){returncheck_same(l,r-p,l+p,r);}};structPalindromeCheck{intn;HashedStringH1,H2;PalindromeCheck(void)=default;PalindromeCheck(std::strings):n(s.size()),H1(s){std::reverse(s.begin(),s.end()),H2.init(s);}inlinevoidinit(std::strings){n=s.size(),H1.init(s);std::reverse(s.begin(),s.end()),H2.init(s);}inlineboolcheck(intl,intr){returnH1.get_hash(l,r)==H2.get_hash(n-1-r,n-1-l);}};#endif // AFSTR_HASHED_STRING
#line 1 "src/alfred/string/hashed-string.hpp"
#include<algorithm>
#include<vector>template<intmod,intseed>structSingleHash{intn;std::vector<int>pow,h;SingleHash(void)=default;SingleHash(std::string&s){init(s);}inlinevoidinit(std::string&s){n=s.size(),h.assign(n+2,0),pow.assign(n+2,1);for(inti=1;i<=n;i++){pow[i]=1ll*pow[i-1]*seed%mod;h[i]=(1ll*h[i-1]*seed+s[i-1])%mod;}}inlineintget_hash(intl,intr){return(h[r+1]-1ll*h[l]*pow[r-l+1]%mod+mod)%mod;}inlineboolcheck_same(intl1,intr1,intl2,intr2){returnget_hash(l1,r1)==get_hash(l2,r2);}};structHashedString{SingleHash<998244353,477>H1;SingleHash<1000000007,233>H2;HashedString(void)=default;HashedString(std::strings):H1(s),H2(s){}inlinevoidinit(std::strings){H1.init(s),H2.init(s);}std::pair<int,int>get_hash(intl,intr){// not recommended.return{H1.get_hash(l,r),H2.get_hash(l,r)};}// caution: index begins with zero.// If index beginning with one is wanted, use s = ' ' + sinlineboolcheck_same(intl1,intr1,intl2,intr2){returnH1.check_same(l1,r1,l2,r2)&&H2.check_same(l1,r1,l2,r2);}inlineboolcheck_period(intl,intr,intp){returncheck_same(l,r-p,l+p,r);}};structPalindromeCheck{intn;HashedStringH1,H2;PalindromeCheck(void)=default;PalindromeCheck(std::strings):n(s.size()),H1(s){std::reverse(s.begin(),s.end()),H2.init(s);}inlinevoidinit(std::strings){n=s.size(),H1.init(s);std::reverse(s.begin(),s.end()),H2.init(s);}inlineboolcheck(intl,intr){returnH1.get_hash(l,r)==H2.get_hash(n-1-r,n-1-l);}};