题意:就是让你求出最小的字符矩阵面积,这个矩阵是这个大矩阵里能够循环的,但是并不一定是全部循环相同的,部分相同也算循环,比如样例。
思路:这题挺好的,以前没有想到二维字符串数组也可以用next数组求出其循环节,现在这题正好补了这个空。
解法:把每一个字符串当做字符进行求next数组,然后求出最小的循环字符串长度,即:len-next[len]。因为以前求循环节是len/(len-next[len]),括号里面的不就是最小的循环长度嘛!
因为要求这个循环矩阵的长和宽,所以长就是每一行作为一个字符串,然后求出最小循环字符串长度;宽就是每一列作为一个字符串,也求出循环长度,相乘即为答案!
刚开始看网上好多代码没看懂,什么最公倍数啊最小覆盖啊,都没看懂博主在干嘛,其实好理很解的嘛二维KMP。上面解释也很清楚了,还不理解的看代码就懂了。
#pragma comment(linker, "/STACK:1024000000,1024000000")//扩内存,因为有的题目可能要开1000*1000的数组
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<map>
#include<queue>
#include<set>
#include<cmath>
#include<bitset>
#define mem(a,b) memset(a,b,sizeof(a))
#define lson i<<1,l,mid
#define rson i<<1|1,mid+1,r
#define llson j<<1,l,mid
#define rrson j<<1|1,mid+1,r
#define INF 6
#define maxn 10005
typedef long long ll;
typedef unsigned long long ull;
using namespace std;
int next[maxn];
char s[maxn][maxn],str[77][maxn],ss[maxn];
int getnext(int len,char p[][maxn])
{
int i,j;
mem(next,0);
next[0]=next[1]=0;
for(i=1;i<len;i++)
{
j=next[i];
while(j&&strcmp(p[i],p[j])) j=next[j];
next[i+1]=(!strcmp(p[i],p[j])?j+1:0);
}
return len-next[len];
}
int main()
{
//freopen("1.txt","r",stdin);
int l,r,i,j;
scanf("%d%d",&l,&r);
for(i=0;i<l;i++)
scanf("%s",s[i]);
for(i=0;i<r;i++)
for(j=0;j<l;j++)
str[i][j]=s[j][i];//取出每一列作为新的字符串,因为宏观上要求列的循环长度
int w=getnext(l,s);//宽
int h=getnext(r,str);//长
printf("%d\n",w*h);
return 0;
}