题目大意:
求出最小的模式块,使得这个模式块经过无限扩展之后可以包含整个给出的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; }
POJ 2185 Milking Grid (KMP),布布扣,bubuko.com
原文地址:http://blog.csdn.net/u010709592/article/details/38017659