这是数算期末的压轴题,一共只有9个人AC了,而且120+的WA…
看了一下觉得题目还是有点思路的,不过实际做起来还是贡献了无数的WA
如果有一个块可以重复的话,那么这个块中的每一行和每一列都一定可以是重复的,因此用kmp算法求出每个行的最小覆盖长度和每一列的最小覆盖长度,然后分别求最小公倍数
值得注意的是最小公倍数有可能大于r,c,因此在循环计算最小公倍数的时候应该额外判断一下。
#include <iostream>
#include <cstdio>
#include <memory.h>
#include <string.h>
using namespace std;
#define maxn 10050
#define maxc 100
int gcd(int a,int b){
return a%b?gcd(b,a%b):b;
}
int lcp(int a,int b){
return a*b/gcd(a,b);
}
char m[maxn][maxc]={0};
int num[maxn]={0};
int main(){
int r,c;
scanf("%d%d",&r,&c);
for(int i=0;i<r;++i){
for(int j=0;j<c;++j){
cin>>m[i][j];
}
}
int mul = 1;
for(int i=0;i<r;++i){
int j=-1;
memset(num,0,sizeof(num));
num[0]=-1;
for(int k=0;k<c;){
if(j==-1||m[i][k]==m[i][j])
num[++k]=++j;
else
j = num[j];
}
mul = lcp(mul,c-num[c]);
if(mul >= c){
mul = c;
break;
}
}
int mul2 = 1;
for(int i=0;i<c;++i){
int j=-1;
memset(num,0,sizeof(num));
num[0]=-1;
for(int k=0;k<r;){
if(j==-1||m[k][i]==m[j][i])
num[++k]=++j;
else
j = num[j];
}
mul2 = lcp(mul2,r-num[r]);
if(mul2 >= r){
mul2 = r;
break;
}
}
int a = mul2*mul;
int b = r*c;
printf("%d\n",a>b?b:a);
//system("pause");
return 0;
}