http://poj.org/problem?id=2185
题意:求最小的模式块,使其无限扩展后包含给你的矩阵块(看别人题解才懂的题意);
分析:假设存在一个模式块可以满足上述条件,那么必然存在一个起点在(0,0)的模式块满足上述条件;
对于每一行,我们找出所有可以满足条件的前缀记录下长度,那么满足所有行的最短的长度就是该模式块的宽r;
对于模式块的长,我们把宽r的字符串压缩看出一个字符,然后再进行KMP,找出该字符串的最小循环串,即长l;
答案就是r * l;
1 #include<cstdio> 2 #include<cstring> 3 #include<iostream> 4 #include<vector> 5 #include<cmath> 6 #include<algorithm> 7 #include<cmath> 8 #include<cstdlib> 9 using namespace std; 10 const int N = 10000+10; 11 int f[N]; 12 void getFail(char *s,int f[]) { 13 int m = strlen(s); 14 f[0] = -1; 15 for (int i = 1; i < m; i++) { 16 int j = f[i-1]; 17 while (j != -1 && s[j+1] != s[i]) j = f[j]; 18 if (s[j+1] == s[i]) j++; 19 f[i] = j; 20 } 21 // for (int i = 0; i < m; i++) cout<<f[i]<<" ";cout<<endl; 22 } 23 int n,m; 24 char mz[N][80]; 25 int cnt[N]; 26 int check(char *s,int x) { 27 int j = 0; 28 for (int i = 0; i < m; i++) { 29 if (s[i] != s[j]) return 0; 30 j++; 31 if (j > x) j = 0; 32 } 33 return 1; 34 } 35 void solve(int r){ 36 f[0] = -1; 37 for (int i = 1; i < n; i++) { 38 int j = f[i-1]; 39 while (j != -1 && strcmp(mz[j+1],mz[i])) j = f[j]; 40 if (strcmp(mz[j+1],mz[i]) == 0) j++; 41 f[i] = j; 42 } 43 // for (int i = 0; i < n; i++) cout<<f[i]<<" ";cout<<endl; 44 printf("%d ",(n - 1 - f[n-1]) * (r)); 45 } 46 int main(){ 47 // getFail("ababab",f); 48 while (~scanf("%d%d",&n,&m)) { 49 memset(cnt,0,sizeof(cnt)); 50 51 for (int i = 0; i < n; i++) { 52 scanf("%s",mz[i]); 53 getFail(mz[i],f); 54 int j = m-1; 55 while (j != -1) { 56 // cout<<m - 1 - f[j]<<endl; 57 cnt[m - 1 - f[j]]++; 58 j = f[j]; 59 } 60 } 61 int r = 0; 62 for (int i = 1; i <= m; i++) if (cnt[i] == n) { 63 r = i; break; 64 } 65 for (int i = 0; i < n; i++) { 66 mz[i][r] = 0; 67 } 68 69 solve(r); 70 } 71 return 0; 72 }