题目大意:
求出最小的模式块,使得这个模式块经过无限扩展之后可以包含整个给出的n*m的矩阵。
思路分析:
首先说说网上其他的求出lcm的解法,我也不太明白为什么所有的lcm就是所求的长和宽。
至少我觉得正解应该是这个方法吧。
首先你可以知道每一行能满足条件的长度。
当这个长度 n 行都满足的话,也就意味着这个长度可以使得n行都经过这个长度扩展得到。
那么我们如何求出所有的长度呢。
比如 abcdab
也就是要在这个串后面加一个 长度为 2 的 "cd" 才满足对吧。而且这个所要得到的长度是4
那么我们求len - next [len] 等于 4.
为什么会这样。你可以画出 next[len ]代表什么。也就是把后面与前缀相同的字符剪掉了。
那么这样我们就求得了r。如何去求c。
这个问题又转化成了
求一个串的最小重复的,可以覆盖整个串的。。
只是二维的。。
#include <cstdio>
#include <iostream>
#include <cstring>
#include <algorithm>
#define maxn 10005
using namespace std;
char str[80];
char map[maxn][80];
int cnt[maxn],next[maxn];
int n,m;
void getnext()
{
int len=m;
next[0]=0;next[1]=0;
for(int i=1;i<len;i++)
{
int j=next[i];
while(j && str[j]!=str[i])j=next[j];
next[i+1]=str[j]==str[i]?j+1:0;
}
}
int main()
{
while(scanf("%d%d",&n,&m)!=EOF)
{
memset(cnt,0,sizeof cnt);
for(int i=0;i<n;i++)
{
scanf("%s",map[i]);
strcpy(str,map[i]);
getnext();
int j=m;
while(j)
{
cnt[m-next[j]]++;
j=next[j];
}
}
int ansr=0;
for(int i=1;i<=m;i++)
if(cnt[i]==n){
ansr=i;
break;
}
for(int i=0;i<n;i++)map[i][ansr]=0;
next[0]=-1,next[1]=0;
for(int i=1;i<n;i++)
{
int j=next[i];
while(j && strcmp(map[j],map[i])!=0)j=next[j];
next[i+1]=strcmp(map[j],map[i])==0?j+1:0;
}
printf("%d\n",(n-next[n])*ansr);
}
return 0;
}