题意:R*C字符矩阵,R<=1e4,C<=75.求出最小子矩阵使得R*C矩阵能被最小子矩阵覆盖.
若为一维,则相当于用kmp求出最小循环节(只要求覆盖,len%(len-next[len])可以不为0)先对每行求最小循环节xi,子矩形的宽度最小为:xi(i=1~r)的最小公倍数lr.
在对每列求最小循环节yi 子矩形的高度最小为:yi(i=1~c)的最小公倍数lc.
以lr*lc子矩阵为单位显然能覆盖整个字符矩阵
#include <iostream>
#include <algorithm>
#include <cstring>
#include <queue>
#include <cstdio>
#include <map>
#include <vector>
using namespace std;
typedef long long ll;
const int N=1e4+20;
const int inf=2e8;
char s[N][80];
int r,c,fail[N];
int gcd(int a,int b)
{
return b==0?a:gcd(b,a%b);
}
int lcm(int a,int b)
{
return a*b/gcd(a,b);
}
void Fail_row(int p)
{
fail[0]=-1;
int i=0,j=-1;
while(i<c)
{
if(j==-1||s[p][i]==s[p][j])
{
fail[i+1]=j+1;
i++,j++;
}
else
j=fail[j];
}
}
void Fail_col(int p)
{
fail[0]=-1;
int i=0,j=-1;
while(i<r)
{
if(j==-1||s[i][p]==s[j][p])
{
fail[i+1]=j+1;
i++,j++;
}
else
j=fail[j];
}
}
int main()
{
while(cin>>r>>c)
{
for(int i=0;i<r;i++)
scanf("%s",s[i]);
int lcmr=1,lcmc=1;
for(int i=0;i<r;i++)
{
Fail_row(i);
lcmr=lcm(lcmr,c-fail[c]);
if(lcmr>=c)
{
lcmr=c;
break;
}
}
for(int i=0;i<c;i++)
{
Fail_col(i);
lcmc=lcm(lcmc,r-fail[r]);
if(lcmc>=r)
{
lcmc=r;
break;
}
}
cout<<lcmr*lcmc<<endl;
}
return 0;
}