题意:给出一个二维的字符矩阵,问最小的可覆盖子矩阵大小。
解法:如果是一维的话,在KMP算法的Next数组中,len-Next[len]是一维的覆盖子串,如果len-Next[len]能整除len,则可恰好覆盖(即长度为len-Next[len]的前缀)。
在二维的情况,每行每列求一个最小公倍数就可以了,并且公倍数不能大于本身总长度。
代码:
/****************************************************
* author:xiefubao
*******************************************************/
#pragma comment(linker, "/STACK:102400000,102400000")
#include <iostream>
#include <cstring>
#include <cstdlib>
#include <cstdio>
#include <queue>
#include <vector>
#include <algorithm>
#include <cmath>
#include <map>
#include <set>
#include <stack>
#include <string.h>
using namespace std;
#define eps 1e-8
typedef long long LL;
char s[11000][100];
int row,col;
int Next[11000];
char tool[11000];
int getNext(char *p)
{
int len=strlen(p);
int i=0;int j=Next[0]=-1;
while(i<len)
{
while(j!=-1&&p[i]!=p[j])j=Next[j];
Next[++i]=++j;
}
return len-Next[len];
}
int gcd(int a,int b)
{
return a==0?b:gcd(b%a,a);
}
int main()
{
while(scanf("%d%d",&row,&col)==2)
{
for(int i=0;i<row;i++)
scanf("%s",s[i]);
long long r=1;
for(int i=0;i<row;i++)
{
for(int j=0;j<col;j++)
tool[j]=s[i][j];
tool[col]='\0';
int k=getNext(tool);
r=k/gcd(r,k)*r;
if(r>=col)
{
r=col;
break;
}
}
long long c=1;
for(int i=0;i<col;i++)
{
for(int j=0;j<row;j++)
tool[j]=s[j][i];
tool[row]='\0';
int k=getNext(tool);
c=k/gcd(c,k)*c;
if(c>=row)
{
c=row;
break;
}
}
cout<<c*r<<'\n';
}
return 0;
}
/*
4 11
abcdabcdabc
efghefghefa
abcdabcdabc
efghefghefg
*/