题目链接:http://poj.org/problem?id=2185
| Time Limit: 3000MS | Memory Limit: 65536K | |
| Total Submissions: 6249 | Accepted: 2616 |
Description
Input
Output
Sample Input
2 5 ABABA ABABA
Sample Output
2
Hint
Source
求出每一行的最小重复子串的长度,所有行的最小重复串的长度的LCM就是最小重复子矩阵的宽。然后对列也做相同的操作。于是就可以求得最小重复子矩阵的大小了。(这里要注意一点:当所得的宽大于原来的宽时,就让等于原来的宽,长也是如此)。
代码如下:
#include<cstdio>
#include<cstring>
#define MAXN 10017
int next[MAXN];
int len;
int row, col;
int subrow[MAXN];
int subcol[87];
char s[MAXN][87];
int LCM(int a, int b)//最小公倍数
{
int x = a, y = b;
int r = x%y;
while(r > 0)
{
x = y;
y = r;
r = x % y;
}
return a*b/y;
}
int getnext_r(int r)//行
{
int i = 0, j = -1;
next[0] = -1;
while(i < col)
{
if(j == -1 || s[r][i] == s[r][j])
{
i++;
j++;
next[i] = j;
}
else
j = next[j];
}
return col - next[col];
}
int getnext_c(int c)//列
{
int i = 0, j = -1;
next[0] = -1;
while(i < row)
{
if(j == -1 || s[i][c] == s[j][c])
{
i++;
j++;
next[i] = j;
}
else
j = next[j];
}
return row - next[row];
}
int main()
{
while(~scanf("%d%d",&row, &col))
{
for(int i = 0; i < row; i++)
{
scanf("%s",s[i]);
}
for(int i = 0; i < row; i++)//统计每一行的重复子串
{
subrow[i] = getnext_r(i);
}
for(int i = 0; i < col; i++)//统计每一列的重复子串
{
subcol[i] = getnext_c(i);
}
int R = 1;
for(int i = 0; i < row; i++)//统计所有行的重复子串的最小公倍数
{
R = LCM(R,subrow[i]);
}
if(R > col)//如果最小公倍数大于了列数就取列数
R = col;
int C = 1;
for(int i = 0; i < col; i++)//统计所有列的重复子串的最小公倍数
{
C = LCM(C,subcol[i]);
}
if(C > row)//如果最小公倍数大于了行数就取行数
C = row;
int ans = R * C;
printf("%d\n",ans);
}
return 0;
}
poj2185 Milking Grid(KMP运用),布布扣,bubuko.com
原文:http://blog.csdn.net/u012860063/article/details/38538415