poj2185:http://poj.org/problem?id=2185
题意:在一个字符矩阵中,找一个最小的字符子矩阵,使其能够覆盖整个矩阵。
题解:在KMP中i-next[i]是这能够覆盖这个串的最小串长度。所以这一题可以用KMP搞。对于每一行求一个最小覆盖,然后取其最小公倍数,如果最大的那个覆盖的2倍不小于串的的长度,那么此时应该取这个长度。然后列也是这个处理,最后把两个数乘起来就是要找的面积。
1 #include<cstdio> 2 #include<cstdlib> 3 #include<cstring> 4 #include<cmath> 5 #include<algorithm> 6 #define N 10005 7 using namespace std; 8 int next[N]; 9 int n,m; 10 char s1[N];//模板串 11 char s2[N];//主串 12 int len1,len2; 13 int ans1,ans2; 14 char str1[N][80]; 15 void getnext(int plen){ 16 int i = 0,j = -1; 17 next[0]=-1; 18 while( i<plen ){ 19 if(j==-1||s1[i]==s1[j]){ 20 ++i;++j; 21 // if(s1[i]!=s1[j] ) 22 next[i] = j; 23 // else 24 // next[i] = next[j]; 25 } 26 else 27 j = next[j]; 28 } 29 } 30 int gcd(int a, int b){ 31 if(b==0) 32 return a; 33 return gcd(b,a%b); 34 } 35 36 37 int lcm(int a, int b){//两个数的最小公倍数 38 return a*b/gcd(a, b); 39 } 40 int main(){ 41 while(~scanf("%d%d",&n,&m)){ 42 ans1=1; 43 ans2=1; 44 int maxn=0; 45 for(int i=1;i<=n;i++){ 46 scanf("%s",s1); 47 strcpy(str1[i],s1); 48 getnext(m); 49 // printf("**%d ",m-next[m]); 50 maxn=max(maxn,m-next[m]); 51 ans1=lcm(ans1,m-next[m]); 52 } 53 for(int i=0;i<m;i++){ 54 for(int j=1;j<=n;j++){ 55 s1[j-1]=str1[j][i]; 56 } 57 getnext(n); 58 59 ans2=lcm(ans2,n-next[n]); 60 } 61 if(maxn*2>=m)ans1=maxn; 62 else if(ans1>m)ans1=m; 63 if(ans2>n)ans2=n; 64 printf("%d ",ans1*ans2); 65 } 66 }