【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 }

 

posted @ 2016-11-17 21:16  konjac蒟蒻  阅读(198)  评论(0编辑  收藏  举报