hdu6153 扩展KMP
hdu6153 A Secret
题意:两个字符串A 、B,问 B 的所有后缀在 A 中出现了多少次。
tags:把两字符串反一下,然后。。就是板子题了。。
#include<bits/stdc++.h> using namespace std; #pragma comment(linker, "/STACK:102400000,102400000") #define rep(i,a,b) for (int i=a; i<=b; ++i) #define per(i,b,a) for (int i=b; i>=a; --i) #define mes(a,b) memset(a,b,sizeof(a)) #define INF 0x3f3f3f3f #define MP make_pair #define PB push_back #define fi first #define se second typedef long long ll; const int N = 1000005, mod = 1e9+7; int nex[N], extend[N]; void getnext(char *T) // nex[i] 表示 T[i~Tlen-1] 与 T的最长公共前缀 { memset(nex, 0, sizeof(nex)); int i, Tlen = strlen(T); nex[0] = Tlen; for(i=0; i<Tlen-1 && T[i]==T[i+1]; ++i) ; nex[1] = i; int a = 1; for(int k=2; k<Tlen; ++k) { int p = a+nex[a]-1, L = nex[k-a]; if( (k-1)+L >= p ) { int j = (p-k+1)>0 ? (p-k+1) : 0; while(k+j<Tlen && T[k+j]==T[j]) ++j; nex[k] = j, a = k; } else nex[k] = L; } } void getextend(char *S, char *T) // extend[i] 表示 S[i~Slen-1]与 T 的最长公共前缀 { getnext(T); int Slen = strlen(S), Tlen = strlen(T), a = 0; int MinLen = Slen>Tlen ? Tlen : Slen; while(a<MinLen && S[a]==T[a]) ++a; extend[0] = a, a = 0; for(int k=1; k<Slen; ++k) { int p = a+extend[a]-1, L = nex[k-a]; if( (k-1)+L >= p ) { int j = (p-k+1)>0 ? (p-k+1) : 0; while(k+j<Slen && j<Tlen && S[k+j]==T[j]) ++j; extend[k] = j, a = k; } else extend[k] = L; } } char A[N], B[N]; int main() { int T; scanf("%d", &T); while(T--) { scanf("%s%s", A, B); int len1 = strlen(A), len2 = strlen(B); reverse(A, A+len1); reverse(B, B+len2); getextend(A, B); ll ans = 0; for(int i=0; i<len1; ++i) { ans += (1LL*extend[i]*(extend[i]+1)/2)%mod; ans %= mod; } printf("%lld\n", ans); } return 0; }