知识链接:点击打开链接
题目链接:点击打开链接
解题思路:将串反过来就是看公共前缀长度了,然后用扩展kmp在用上等差求和就可以轻松解决
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int mx = 1e6+10,mod = 1e9+7;
int nexts[mx],Pextend[mx];
char Ts[mx],str[mx];
int Tlen,Slen,n,m;
void Getnext(int len)
{
nexts[0] = len,nexts[1] = 0;
int j = 0,k = 1,po,pos;
while(Ts[k++]==Ts[j++]) nexts[1]++;
po = 1,pos = nexts[1]+1;
for(int i=2;i<len;i++){
int lon = nexts[i-po];
if(i+lon<pos) nexts[i] = lon;
else{
if(pos<i) pos = i;
nexts[i] = pos - i;
j = pos,k = pos-i;
while(j<len&&Ts[j++]==Ts[k++]) nexts[i]++;
po = i,pos = i + nexts[i];
}
//cout << "next:" << nexts[i] << endl;
}
}
void Getextend(int len,int *extend)
{
int j = 0,k = 0;
extend[0] = 0;
while(j<Tlen&&Ts[j++]==str[k++]) extend[0]++;
int po = 0,pos = extend[0];//扩展到最长地方的位置和他扩展的位置
for(int i=1;i<len;i++){
int lon = nexts[i-po];
if(i+lon<pos) extend[i] = lon;//没有超过当前最长长度说明他只能到这里
else{
if(pos<i) pos = i;
extend[i] = pos - i;//先确定他是可以到达p的
j = pos,k = pos - i;
while(j<len&&str[j++]==Ts[k++]) extend[i]++;//然后向后继续扩展
po = i,pos = i + extend[i];//更新po和pos
}
//cout << pos << " " << extend[i] << endl;
}
}
//bool vis[mx];
int main()
{
int t;
scanf("%d",&t);
while(t--){
scanf("%s%s",str,Ts);
Slen = strlen(str);
Tlen = strlen(Ts);
reverse(str,str+Slen);
reverse(Ts,Ts+Tlen);
Getnext(Tlen);
Getextend(Slen,Pextend);
ll ans = 0;
for(int i=0;i<Slen;i++)
ans = (ans + (1ll*Pextend[i]*Pextend[i]+Pextend[i])/2)%mod;
printf("%lld\n",ans);
}
return 0;
}