首页 > 代码库 > POJ 2185 Milking Grid (KMP)

POJ 2185 Milking Grid (KMP)

题目大意:

求出最小的模式块,使得这个模式块经过无限扩展之后可以包含整个给出的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;
}