A Secret HDU - 6153(扩展kmp)
题意要你求b串每一个后缀对a串的每一个后缀的匹配长度之和
将两个串倒过来
用这时的b串的前缀去匹配a的后缀
这时候所k处匹配的结果就是以k为终点,有最长可以匹配向后到extend[k]长度
对于每一个点等差数列求和 累加
#include<bits/stdc++.h> using namespace std; #define ll long long #define mem(a,b) memset(a,b,sizeof(a)) #define inf 0x3f3f3f3f const int maxn=1e6+10; int mod=1e9+7; int nxt[maxn],extend[maxn]; int q; char s[maxn],t[maxn]; void getnxt() { int l=strlen(t); nxt[0]=l; int now=0; while(t[now]==t[now+1]&&now+1<l) now++; nxt[1]=now; int p0=1;//可以到达最远位置的i for(int i=2;i<l;i++) { if(i+nxt[i-p0]<nxt[p0]+p0) nxt[i]=nxt[i-p0]; else { int now=nxt[p0]+p0-i; now=max(now,0);//这里是为了防止i>p的情况 while(t[now]==t[i+now]&&i+now<l) now++; nxt[i]=now; p0=i; } } } void exkmp() { getnxt(); int now=0; int l=strlen(s); int l1=strlen(t); int lim=min(l,l1); while(s[now]==t[now]&&now<lim) now++; extend[0]=now; int p0=0; for(int i=1;i<l;i++) { if(i+nxt[i-p0]<extend[p0]+p0) extend[i]=nxt[i-p0]; else { int now=extend[p0]+p0-i; now=max(now,0); while(t[now]==s[i+now]&&now<l1&&now+i<l) now++; extend[i]=now; p0=i; } } } int main() { int mub; scanf("%d",&mub); while(mub--) { scanf("%s%s",s,t); int l=strlen(s); int l1=strlen(t); reverse(t,t+l1); reverse(s,s+l); // cout<<s<<endl; // cout<<t<<endl; // cout<<s<<endl; // cout<<t<<endl; mem(nxt,0); mem(extend,0); exkmp(); ll ans=0; for(int i=0;i<l;i++) { ans=(ans+(1ll*extend[i]*(extend[i]+1)/2)%mod)%mod; // ans+=extend[i]; } printf("%d\n",ans); /*int l=t.size(),l1=s.size(); for(int i=0;i<l;i++) { cout<<nxt[i]<<" "; }cout<<endl; for(int i=0;i<l1;i++) { cout<<extend[i]<<" "; }cout<<endl;*/ } return 0; }