「题解」:串串香
问题 A: 串串香
时间限制: 1 Sec 内存限制: 512 MB
题面
题面谢绝公开。
题解
吃字符串可海星……正解KMP,然而我就是用hash水过233333。
直接串内匹配,看是否能拆成更小的字符串。从小到大枚举长度,不是约数直接跳过,是约数再匹配。
预处理一个hash前缀和直接搞就完了。
代码:
#include<bits/stdc++.h>
#define int long long
#define rint register int
#define ull unsigned long long
using namespace std;
const int Z=2333;
int T,n,m,ans,len,blo;
ull hs[1000006],JZ[1000006];
char ch[1000006];
bool _ok;
signed main()
{
// freopen("ex_ccx2.in","r",stdin);
// freopen("my.out","w",stdout);
scanf("%lld",&T);
while(T--)
{
scanf("%lld %lld %s",&n,&m,ch+1);JZ[0]=1;
if(m==1){printf("%lld\n",n-1);continue;}
bool te=1;
for(rint i=1;i<=m;++i)
{
hs[i]=hs[i-1]*Z+(ch[i]-'A'+1);
if(ch[i]!='A')te=0;
JZ[i]=JZ[i-1]*Z;
}
if(te){printf("%lld\n",n*m-1);continue;}
if(n*m<=1000000)
{
ans=0;JZ[0]=1;
for(rint i=1;i<=n;++i)
for(rint j=1;j<=m;++j)
{
rint lin=(i-1)*m+j;
hs[lin]=hs[lin-1]*Z+(ch[j]-'A'+1);
JZ[lin]=JZ[lin-1]*Z;
}
for(rint i=1;i<n*m;++i)
if(hs[i]==hs[n*m]-hs[n*m-i]*JZ[i])ans=i;
printf("%lld\n",ans);
continue;
}
len=0,blo=0;
for(rint i=1;i<=(m/2);++i)
{
if(m%i!=0)continue;_ok=1;
for(rint j=2;j<=(m/i);++j)
if((hs[i*(j-1)]-hs[i*(j-2)]*JZ[i])!=(hs[j*i]-hs[i*(j-1)]*JZ[i])){_ok=0;break;}
if(_ok){len=i,blo=m/len;break;}
}
printf("%lld\n",(n-1)*m+(blo-1)*len);
}
return 0;
}
浙公网安备 33010602011771号