题意:
给出一个矩阵,求最小的子矩阵是的,子矩阵通过不断复制扩大能包含原矩阵。
题解:
直接按行和按列求最小循环节,然后求行最小循环节的最小公倍数,以及列的最小循环节的最小公倍数,然后就是两个最小公倍数相乘了。但是注意最小公倍数会大于行的长度或列的长度,所以要判断处理下。
#include<iostream>
#include<math.h>
#include<stdio.h>
#include<algorithm>
#include<string.h>
using namespace std;
typedef __int64 ll;
#define oo 0x3f3f3f3f
const int MOD=1000000007;
const int maxn=10005;
int next[maxn];
char maze[maxn][80];
int R,C;
void get_next1(int id)
{
int i=0;
next[i]=-1;
int j=-1;
while(i<C)
{
if(j==-1||maze[id][i]==maze[id][j])
{
i++;
j++;
next[i]=j;
}
else j=next[j];
}
}
void get_next2(int id)
{
int i=0;
next[i]=-1;
int j=-1;
while(i<R)
{
if(j==-1||maze[i][id]==maze[j][id])
{
i++;
j++;
next[i]=j;
}
else j=next[j];
}
}
int gcd(int a,int b)
{
return b==0 ? a : gcd(b,a%b);
}
int C_M(int a,int b)
{
if(a<b)
{
int temp=a;
a=b;
b=temp;
}
return a*b/gcd(a,b);
}
int main()
{
int comR,comC,temp;
while(scanf("%d %d",&R,&C)!=EOF)
{
for(int i=0;i<R;i++)
scanf("%s",maze[i]);
for(int i=0;i<R;i++)
{
get_next1(i);
if(i==0)
comR=C-next[C];
else
{
temp=C-next[C];
comR=C_M(comR,temp);
}
if(comR>C)
comR=C;
}
for(int i=0;i<C;i++)
{
get_next2(i);
if(i==0)
comC=R-next[R];
else
{
temp=R-next[R];
comC=C_M(comC,temp);
}
if(comC>R)
comC=R;
}
printf("%d\n",comR*comC);
}
return 0;
}