TopCoder SRM 433 Div1 Easy MagicWords
問題
文字列Tがmagic wordであるとは、
Tをi(0≦i<|T|)文字シフトした文字列がTに等しくなるようなiがちょうどK個あることを言う。
n個の文字列が与えられる。
0からn-1の数の順列p[i]について、この順に
これらの文字列を結合した文字列をSとする。
Sがmagic wordになるような順列はいくつあるか、求めよ。
制約条件
n≦8
各文字列の長さ≦20
K≦200
方針
まずは、順列から文字列を全生成する。
そのあと、文字列がmagic wordかどうかを判定するが、これをナイーブにやると
O(文字列長さ^2)の時間がかかりTLE.
rolling hashを使ってO(文字列の長さ)の時間でやるようにすれば制限時間に間に合う。
ソースコード
typedef unsigned long long ll; ll hash[1000],pw[1000]; bool magic(int k,string &s){ int n=s.size(); s+=s; hash[0]=0; pw[0]=1; rep(i,n*2)pw[i+1]=pw[i]*29; rep(i,n*2)hash[i+1]=hash[i]+(s[i]-'A'+1)*pw[i]; rep(i,n)if(hash[i+n]-hash[i]==hash[n]*pw[i])k--; return k==0; } class MagicWords { public: int count(vector <string> S, int K) { vi ord; int n=S.size(),ans=0; rep(i,n)ord.pb(i); do{ string s; rep(i,n)s+=S[ord[i]]; if(magic(K,s))ans++; }while(next_permutation(all(ord))); return ans; } };