题目链接:
http://poj.org/problem?id=2185
题目大意:
有一个N行M列的字符矩阵,这个字符矩阵可以由较小的矩阵重复平铺组成整个矩阵。问:
最小的字符子矩阵的面积为多少。
思路:
对于长度为M的每一行s[i]来说,M-Next[M],M-Next[Next[M]],…都是能通过复制,完
全覆盖字符串的可行串,而M-Next[M]是最小的。遍历每一行,求出对所有s[i]都可行的最
小字符串长度,即每一行M-Next[M]的最小公倍数lcmn。再用类似的方法求出长度为N、
对每一列都可行的最小字符串高度,即每一列N-Next[N]的最小公倍数lcmm。则最后结果
就是lcmn*lcmm。
AC代码:
#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
using namespace std;
const int MAXN = 10010;
int Next[MAXN],Num[110],M,N;
char s[MAXN][110];
int Gcd(int a,int b)
{
if(a < b)
int temp = a,a = b,b = temp;
if(b == 0)
return a;
return Gcd(b,a%b);
}
int Lcm(int a,int b)
{
return a/Gcd(a,b)*b;
}
void GetNext1(int h)
{
int i = 0,j = -1;
int len = strlen(s[h]);
Next[0] = -1;
while(i <= len)
{
if(j == -1 || s[h][i]== s[h][j])
{
i++,j++;
Next[i] = j;
}
else
j = Next[j];
}
}
void GetNext2(int w)
{
int i = 0,j = -1;
int len = N;
Next[0] = -1;
while(i <= len)
{
if(j == -1 || s[i][w] == s[j][w])
{
i++,j++;
Next[i] = j;
}
else
j = Next[j];
}
}
int main()
{
while(cin >> N >> M)
{
getchar();
int lcmn = 1;
for(int i = 0; i < N; ++i)
cin >> s[i];
for(int i = 0; i < N; ++i)
{
GetNext1(i);
lcmn = Lcm(lcmn,M-Next[M]);
if(lcmn >= M)
{
lcmn = M;
break;
}
}
int lcmm = 1;
for(int i = 0; i < M; ++i)
{
GetNext2(i);
lcmm = Lcm(lcmm,N-Next[N]);
if(lcmm >= N)
{
lcmm = N;
break;
}
}
cout << lcmm*lcmn << endl;
}
return 0;
}