反转字符串就可以用kmp的,因为要求是后缀,把两个字符串都反转就可以用kmp了,kmp是用来求前缀的。所以对第二个串求next数组,如果不能继续匹配就进行1+2+3+4+……j处理。
Ac代码
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <math.h>
#include <iostream>
using namespace std;
const int maxn=1000009;
char s1[maxn],s2[maxn];
int nxt[maxn];
const int mod=1e9+7;
void get_nxt(char *s)
{
int j,k;
nxt[0]=-1;
j=0;
k=-1;
int n=strlen(s);
while(j<n)
{
if(k==-1||s[j]==s[k])
{
j++;
k++;
nxt[j]=k;
}
else k=nxt[k];
}
}
long long solve(long long n)
{
// cout<<(n*(n+1)/2)<<endl;
if(n>=1)return n*(n+1)/2;
else return 0;
}
void kmp(char *s1,char *s2)
{
get_nxt(s2);
// printf("%d\n",nxt[2]);
int n1,n2,j=0,i=0;
n1=strlen(s1);
n2=strlen(s2);
long long ans=0;
for(;i<n1;)
{
// cout<<i<<" "<<j<<endl;
// getchar();
if(s1[i]==s2[j]||j==-1)
{
i++;
j++;
}
else {
ans+=solve(j);
j=nxt[j];
ans%=mod;
}
if(j==n2){
ans+=solve(j);
j=nxt[j];
ans%=mod;
}
}
while(j>0){ans+=solve(j); j=nxt[j];ans%=mod;}
cout<<ans<<endl;
}
int main()
{
int t;
scanf("%d%*c",&t);
while(t--)
{
memset(nxt,0,sizeof(0));
gets(s1);
gets(s2);
int len1=strlen(s1),len2;
len2=strlen(s2);
reverse(s1,s1+len1);
reverse(s2,s2+len2);
kmp(s1,s2);
}
return 0;
}