解题思路
超开心!!终于A了一道题!!原本可以再A一题的啊啊啊啊!!!
涉及到公共子串,直接上KMP。先算出每一个b中有几个a,但是我们发现将b倍长n倍后,首尾相接处可能还有a。于是可以处理两倍b中含a的个数 w w w和一倍b中含a的个数 w w ww ww,然后 w w − w ∗ 2 ww-w*2 ww−w∗2就是收尾处的子串数,r让 w w = w w − w ∗ 2 ww=ww-w*2 ww=ww−w∗2,最后wn+ww(n-1)就是答案啦。
代码
#include<iostream>
#include<cmath>
#include<cstring>
#include<cstdio>
#include<algorithm>
#define ll long long
using namespace std;
ll n,w,ww,p[100010];
char s[100010],t[100010],tt[200010];
ll kmp(char a[],char b[])
{
ll ans=0;
for(int i=0,j=0;i<strlen(b+1);i++)
{
while(j>0&&b[i+1]!=a[j+1])
j=p[j];
if(b[i+1]==a[j+1])
j++;
if(j==strlen(a+1))
{
ans++;
j=p[j];
}
}
return ans;
}
int main(){
scanf("%lld",&n);
scanf("%s",s+1);scanf("%s",t+1);
for(int i=1;i<=strlen(t+1);i++)
{
tt[i]=t[i];
tt[strlen(t+1)+i]=t[i];
}
p[1]=0;
for(int i=1,j=0;i<strlen(s+1);i++)
{
while(j>0&&s[i+1]!=s[j+1])
j=p[j];
if(s[i+1]==s[j+1])
j++;
p[i+1]=j;
}
w=kmp(s,t);
ww=kmp(s,tt);
ww=ww-w*2;
printf("%lld",w*n+ww*(n-1));
}
/*
2
ababa
bababa
*/