传送门:HTTP://acm.hdu.edu.cn/showproblem.php PID = 6153
题意:给你两个串a,b求b串的所有后缀在a串的出现次数*后缀串长度和
思路:反转两个串把后缀变前缀kmp统计前缀注意kmp统计时ababab时经历会存在大前缀串的前缀是反转b的前缀需要单独统计
码:
#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
const int mod = 1e9 + 7;
const int maxn = 1e6 + 100;
LL ans;
char S[maxn], T[maxn];
int slen,tlen;
int nextk[maxn];
void getnextk()
{
int j = 0, k = -1;
nextk[0] = -1;
while(j < tlen)
{
if(k == -1 || T[j] == T[k]) nextk[++j] = ++k;
else k = nextk[k];
}
}
int f[maxn];
void KMP_Count()
{
if(slen == 1 && tlen == 1){ans = (S[0] == T[0]);return;}
getnextk();
int i, j = 0;
for(i = 0; i < slen; i++)
{
while(j > 0 && S[i] != T[j])
{
j = nextk[j];
}
if(S[i] == T[j]) j++;
f[j]++;
if(j == tlen) j = nextk[j];
}
for(int i=tlen;i>=1;i--) f[ nextk[i] ]+=f[i];///长度为i对于前缀是否有相同段
for(int i=tlen;i>=1;i--)
{
ans=(ans+(LL)f[i]*i%mod)%mod,f[i]=0;
}
}
int main()
{
int t;
scanf("%d", &t);
for(int cas = 1; cas <= t; cas++)
{
scanf("%s", S);
slen = strlen(S);
reverse(S, S + slen);
scanf("%s", T);
tlen = strlen(T);
reverse(T, T + tlen);
ans = 0;
KMP_Count();
printf("%lld\n", ans);
}
return 0;
}