题目大意
求一个串在另一个串复制n遍的串出现几遍。
题解
显然将两个串做kmp,有很多重复,可以先把第二个串复制到比第一个串长,计算结果,增长一个串,计算结果,计算有多少个增长串,得到最终结果。
code
#include<set>
#include<cmath>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define LL long long
#define fo(i,j,k) for (int i=j;i<=k;i++)
#define fd(i,j,k) for (int i=j;i>=k;i--)
using namespace std;
LL const maxn=100000 ;
LL n,sn,tn,fail [maxn+10 ],match [maxn*5 +10 ];
char s[maxn+10 ],t[maxn*5 +10 ];
int main(){
freopen("d.in" ,"r" ,stdin);
freopen("d.out" ,"w" ,stdout);
scanf("%lld\n" ,&n);
scanf("%s\n" ,s+1 );sn=strlen(s+1 );
scanf("%s\n" ,t+1 );tn=strlen(t+1 );
LL m=(sn-1 )/tn+1 ;
fo(i,tn+1 ,tn*m+tn)t[i]=t[i-tn];
fo(i,2 ,sn){
fail [i]=fail [i-1 ];
for (;fail [i]&&(s[fail [i]+1 ]!=s[i]);fail [i]=fail [fail [i]]);
if (s[fail [i]+1 ]==s[i])fail [i]++;
}
fo(i,1 ,min(tn*n,tn*m+tn)){
match [i]=match [i-1 ];
for (;match [i]&&(s[match [i]+1 ]!=t[i]);match [i]=fail [match [i]]);
if (s[match [i]+1 ]==t[i])match [i]++;
}
if (tn*n<=tn*m+tn){
LL ans=0 ;
fo(i,1 ,tn*n)if (match [i]==sn)ans++;
printf("%lld" ,ans);
return 0 ;
}
LL tmp=0 ;
fo(i,1 ,tn*m)if (match [i]==sn)tmp++;
LL tmp2=0 ;
fo(i,tn*m+1 ,tn*m+tn)if (match [i]==sn)tmp2++;
printf("%lld" ,tmp+tmp2*(n-m));
return 0 ;
}