hdu 5782 Cycle(KMP+hash)
题目链接:hdu 5782 Cycle
题意:
给出两个字符串,判断他们每一个前缀是否循环同构,循环同构的意思就是,字符串首位相接拼成一个环,两个环通过旋转可以相等。
题解:
1 #include<bits/stdc++.h> 2 #define mst(a,b) memset(a,b,sizeof(a)) 3 #define F(i,a,b) for(int i=(a);i<=(b);++i) 4 using namespace std; 5 typedef unsigned long long ull; 6 7 const int N=1e4+7; 8 9 struct string_hash{ 10 const static int seed=1331; 11 static ull b[N]; 12 int len;ull h[N]; 13 inline int idx(char x){return x-'a'+1;} 14 static void init(){b[0]=1;F(i,1,N-1)b[i]=b[i-1]*seed;} 15 void ins(char *s) 16 { 17 len=strlen(s+1); 18 F(i,1,len)h[i]=h[i-1]*seed+idx(s[i]); 19 } 20 inline ull ask(int l,int r){return h[r]-b[r-l+1]*h[l-1];} 21 }a[2]; 22 ull string_hash::b[N]; 23 24 char sa[N],sb[N]; 25 int nxt[N],ans[N]; 26 27 int check(int n,int m,int op) 28 { 29 if(n==m)return 1; 30 return a[op].ask(m+1,n)==a[op^1].ask(1,n-m); 31 } 32 33 void KMP(int n, char*a, int m, char*b,int op) { 34 int i, j; 35 for (nxt[0] = j = -1, i = 1; i < n; nxt[i++] = j) { 36 while (~j&&a[j + 1] != a[i])j = nxt[j]; 37 if (a[j + 1] == a[i])j++; 38 } 39 for (j = -1, i = 0; i < m; i++) { 40 while (~j&&a[j + 1] != b[i])j = nxt[j]; 41 if (a[j + 1] == b[i]) 42 { 43 j++; 44 if(!ans[i])ans[i]=check(i+1,j+1,op); 45 } 46 if (j == n - 1) j = nxt[j]; 47 } 48 } 49 50 int main(){ 51 string_hash::init(); 52 while(~scanf("%s%s",sa+1,sb+1)) 53 { 54 a[0].ins(sa),a[1].ins(sb); 55 mst(ans,0); 56 KMP(a[0].len,sa+1,a[0].len,sb+1,0); 57 KMP(a[0].len,sb+1,a[0].len,sa+1,1); 58 ans[a[0].len+1]=0; 59 F(i,0,a[0].len-1)printf("%d",ans[i]); 60 puts(""); 61 } 62 return 0; 63 }