【poj 2185】Milking Grid(字符串--KMP+问题分解)
题意:给定一个由字符组成的矩阵,求出它的面积最小的覆盖矩阵。(感觉应该是可重叠的......* (・ω・)っ)
解法:KMP。行列互不影响,可以问题分解。先求出每一行的最小重复串,利用kmp中的next[ ]数组,然后求其最小公倍数。若变成最大值就可以break了,这也是我代码本来应该O(2*m*n),但却32ms很快的原因......(๑•ᴗ•๑) 于是同样地求每一列的最小重复串,再求最小公倍数。最终2个答案相乘就行了。
P.S.这题我十分纠结,也有人说poj数据水......但我还是AC了~屏蔽的都是我纠结的。
1 #include<cstdio> 2 #include<cstdlib> 3 #include<cstring> 4 #include<iostream> 5 using namespace std; 6 7 const int N=10010,M=80; 8 char s[N][M]; 9 int n,m; 10 int next[N];//,tend[M]; 11 12 int gcd(int a,int b) {return b?gcd(b,a%b):a;} 13 int lcm(int x,int y) {return x*y/gcd(x,y);} 14 int kmp() 15 { 16 int p,xx=1,yy=1; 17 for (int i=1;i<=n;i++) 18 { 19 memset(next,0,sizeof(next)); 20 next[1]=0; p=0; 21 for (int j=2;j<=m;j++) 22 { 23 while (s[i][j]!=s[i][p+1] && p) p=next[p]; 24 if (s[i][j]==s[i][p+1]) p++; 25 next[j]=p; 26 } 27 /*int t=m-p,tt; 28 if (t%(t-next[t])!=0) tt=t; 29 else tt=t-next[t];*/ 30 //if (m%(m-next[m])!=0) {xx=m;break;} 31 //else 32 xx=lcm(xx,m-next[m]); 33 if (xx>=m) {xx=m;break;} 34 } 35 for (int i=1;i<=m;i++) 36 { 37 memset(next,0,sizeof(next)); 38 next[1]=0; p=0; 39 for (int j=2;j<=n;j++) 40 { 41 while (s[j][i]!=s[p+1][i] && p) p=next[p]; 42 if (s[j][i]==s[p+1][i]) p++; 43 next[j]=p; 44 } 45 //if (n%(n-next[n])!=0) {yy=n;break;} 46 //else 47 yy=lcm(yy,n-next[n]); 48 if (yy>=n) {yy=n;break;} 49 } 50 return xx*yy; 51 } 52 int main() 53 { 54 scanf("%d%d",&n,&m); 55 for (int i=1;i<=n;i++) 56 scanf("%s",s[i]+1); 57 printf("%d\n",kmp()); 58 return 0; 59 }