poj2185 Milking Grid 二维kmp

来源:互联网 发布:做淘宝买什么电脑好 编辑:程序博客网 时间:2024/05/22 10:27

     给一个字符矩阵,求一个最小的矩阵,使得这个矩阵复制若干次可以完整包含原矩阵。首先考虑行,找出每行的最小重复单元的长度后,他们的最小公倍数就是横向上的最小单元长度;同理纵向上求出纵向上的最小单元长度,要注意的一点是如果这两个长度大于n或m得话,就取n或m,因为最长也就是他们本身的长度..那么现在的问题就是求一行(或一列)的最小重复单元了,求出该行的失配函数,len-f[len]就是这一行的最小重复单元的长度,举个例子

12345678

     12345678

如果f[8]=3,显然后345678=123456,而下面的78又等于上面的78,因此等于下面的56,一次类推就会得到12=34=56=78,也就是整个串是由12重复否成的。理解了这点,剩下的就是对每行求一下重复单元的长度,最后组合一下最小公倍数,对每列做同样的操作,最后ansx*ansy就是答案。

#include <iostream>#include <algorithm>#include <cmath>#include <cstdio>#include <algorithm>#include <stack>#include <queue>#include <map>#include <string>#include <cstring>#include <string>using namespace std;typedef long long ll;const int maxn=10020;char mat[10020][100];char str[maxn],s[maxn],s1[maxn];int f[maxn];void getFail(char* P,int* f){    int m=strlen(P);    f[0]=0;    f[1]=0;    for (int i=1; i<m; i++)    {        int j=f[i];        while(j && P[i]!=P[j]) j=f[j];        f[i+1]=P[i]==P[j]?j+1:0;    }}int find(char* T,char* P,int* f){    int n=strlen(T);    int m=strlen(P);    getFail(P,f);    int j=0;    for (int i=0; i<n; i++)    {        while(j && P[j]!=T[i]) j=f[j];        if (P[j]==T[i]) j++;        if (j==m) return i-m+1;    }}ll gcd(ll x,ll y){    if (y==0) return x;    return gcd(y,x%y);}ll lcs(ll x,ll y){    return x*y/gcd(x,y);}int n,m,k;int main(){//    freopen("in.txt","r",stdin);    while(~scanf("%d%d",&n,&m))    {        for (int i=0; i<n; i++)        scanf("%s",mat[i]);        strcpy(s,mat[0]);        getFail(s,f);        ll ans=strlen(s)-f[strlen(s)];        ll x;        for (int i=1; i<n; i++)        {            strcpy(s,mat[i]);            getFail(s,f);            x=strlen(s)-f[strlen(s)];            ans=lcs(ans,x);        }        if (ans>m) ans=m;        ll ans1;        for (int j=0; j<n; j++)        s[j]=mat[j][0];        s[n]='\0';        getFail(s,f);        ans1=strlen(s)-f[strlen(s)];        for (int i=1; i<m; i++)        {            for (int j=0; j<n; j++)            s[j]=mat[j][i];            s[n]='\0';            getFail(s,f);            x=strlen(s)-f[strlen(s)];            ans1=lcs(ans1,x);        }        if (ans1>n) ans1=n;        printf("%lld\n",ans*ans1);    }    return 0;}


0 0
原创粉丝点击