知识链接:点击打开链接

题目链接:点击打开链接

解题思路:将串反过来就是看公共前缀长度了,然后用扩展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;
}