#挺难的题 数据水 看了几篇题解才确定了正确做法
对于一个长度为n的字符串,kmp一遍,它的最短题目要求的长度为n-nxt[n]
a个不可分割出循环节的字符串连在一起是不可写成b个连在一起的形式的(a,b互质)
但是对于AAAABAAA,符合的长度有5,6,7,8并不全是8-nxt[8]=5的倍数 所以在得出5这个答案后 要把后面三个(AAA)再kmp一次得到1,所以答案为5,5+1,5+1+1,5+1+1+1
由于r<=75用一个数组统计这些长度出现次数 每次+1,最后从小到大扫若某个长度出现了r次就是我们要的答案的宽
然后对于1-r行再kmp得到长 相乘得到答案
代码
#include<iostream>
#include<cstdio>
#include<string>
using namespace std;
int r,c;
int cnt[80];
string a[10005];
int nxt[10005];
int main()
{
cin>>r>>c;
for(int i=1;i<=r;++i)
{
cin>>a[i];
string s=a[i];
int pt=0;
while(s.size())
{
for(int j=2,k=0;j<=s.size();++j)
{
while(k&&s[k+1-1]!=s[j-1])k=nxt[k];
if(s[k+1-1]==s[j-1])++k;
nxt[j]=k;
}
int l=s.size()-nxt[s.size()];
int j;
for(j=pt+l;j<=a[i].size();j+=l)++cnt[j];
pt=j-l;
s=a[i].substr(pt,a[i].size()-pt);
}
}
for(int i=2,j=0;i<=r;++i)
{
while(j&&a[i]!=a[j+1])j=nxt[j];
if(a[i]==a[j+1])++j;
nxt[i]=j;
}
for(int i=1;i<=c;++i)
{
if(cnt[i]==r)
{
cout<<i*(r-nxt[r])<<endl;
break;
}
}
return 0;
}