http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=4629
后缀数组或扩展kmp
SA做法
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <queue>
#include <algorithm>
#include <vector>
#include <cstring>
#include <stack>
#include <cctype>
#include <utility>
#include <map>
#include <string>
#include <climits>
#include <set>
#include <string>
#include <sstream>
#include <ctime>
#include <bitset>
#include <iomanip>
#pragma comment(linker, "/STACK:102400000,102400000")
using std::priority_queue;
using std::vector;
using std::swap;
using std::stack;
using std::sort;
using std::max;
using std::min;
using std::pair;
using std::map;
using std::string;
using std::cin;
using std::cout;
using std::set;
using std::queue;
using std::string;
using std::stringstream;
using std::make_pair;
using std::getline;
using std::greater;
using std::endl;
using std::multimap;
using std::deque;
using std::unique;
using std::lower_bound;
using std::random_shuffle;
using std::bitset;
using std::upper_bound;
using std::multiset;
using std::ios;
using std::make_heap;
using std::push_heap;
using std::pop_heap;
typedef long long LL;
typedef unsigned long long ULL;
typedef unsigned UN;
typedef pair<int, int> PAIR;
typedef multimap<int, int> MMAP;
typedef long double LF;
const int MAXN(200010);
const int MAXM(20010);
const int MAXE(2100010);
const int MAXK(6);
const int HSIZE(1313131);
const int SIGMA_SIZE(26);
const int MAXH(19);
const int INFI((INT_MAX-1) >> 1);
const ULL BASE(31);
const LL LIM(1e13);
const int INV(-10000);
const int MOD(1000000007);
const double EPS(1e-7);
const LF PI(acos(-1.0));
template<typename T> inline bool checkmax(T &a, T b){if(b > a) { a = b; return true;} return false;}
template<typename T> inline bool checkmin(T &a, T b){if(b < a) { a = b; return true;} return false;}
template<typename T> inline T ABS(T a){return a < 0? -a: a;}
template<typename T> inline bool EZ(T a){return ABS(a) < EPS;}
int Log[MAXN];
void initLog(){
Log[0] = -1;
for(int i = 1; i < MAXN; ++i) Log[i] = (i&(i-1))? Log[i-1]: Log[i-1]+1;
}
struct SA{
char S[MAXN];
int sa[MAXN], t1[MAXN], t2[MAXN], cnt[MAXN], len, M;
void init(int l, int m = 128){
len = l;
M = m;
int *p1 = t1, *p2 = t2;
for(int i = 0; i < M; ++i) cnt[i] = 0;
for(int i = 0; i <= len; ++i) ++cnt[p1[i] = S[i]];
for(int i = 1; i < M; ++i) cnt[i] += cnt[i-1];
for(int i = len; i >= 0; --i) sa[--cnt[p1[i]]] = i;
int temp = 1;
for(int k = 1; temp <= len; k <<= 1){
temp = 0;
for(int i = len-k+1; i <= len; ++i) p2[temp++] = i;
for(int i = 0; i <= len; ++i)
if(sa[i] >= k) p2[temp++] = sa[i]-k;
for(int i = 0; i < M; ++i) cnt[i] = 0;
for(int i = 0; i <= len; ++i) ++cnt[p1[p2[i]]];
for(int i = 1; i < M; ++i) cnt[i] += cnt[i-1];
for(int i = len; i >= 0; --i) sa[--cnt[p1[p2[i]]]] = p2[i];
swap(p1, p2);
temp = 1;
p1[sa[0]] = 0;
for(int i = 1; i <= len; ++i)
p1[sa[i]] = p2[sa[i-1]] == p2[sa[i]] && p2[sa[i-1]+k] == p2[sa[i]+k]? temp-1: temp++;
M = temp;
}
}
int rank[MAXN], hei[MAXN];
void getHei(){
int k = 0;
for(int i = 0; i <= len; ++i) rank[sa[i]] = i;
for(int i = 0; i < len; ++i){
if(k) --k;
int j = sa[rank[i]-1];
while(S[i+k] == S[j+k]) ++k;
hei[rank[i]] = k;
}
}
int dp[MAXH][MAXN];
void initRMQ(){
for(int i = 1; i <= len; ++i) dp[0][i] = hei[i];
for(int i = 1; (1 << i) <= len; ++i)
for(int j = 1; j+(1 << i)-1 <= len; ++j)
dp[i][j] = min(dp[i-1][j], dp[i-1][j+(1 << (i-1))]);
}
int lcp(int a, int b){
if(a == b) return len-a;
if(a == len || b == len) return 0;
a = rank[a];
b = rank[b];
if(a > b) swap(a, b);
++a;
int temp = Log[b-a+1];
return min(dp[temp][a], dp[temp][b-(1 << temp)+1]);
}
int solve(int ind, int lim){
ind = rank[ind];
int ret = 0;
int l = 0, r = ind;
while(l < r){
int m = (l+r) >> 1;
if(lcp(sa[m], sa[ind]) >= lim) r = m;
else l = m+1;
}
ret += ind-l+1;
l = ind, r = len+1;
while(l < r){
int m = (l+r) >> 1;
if(lcp(sa[m], sa[ind]) >= lim) l = m+1;
else r = m;
}
--l;
ret += l-ind+1;
--ret;
return ret;
}
} sa1, sa2;
int main(){
initLog();
int TC;
scanf("%d", &TC);
while(TC--){
scanf("%s%s", sa1.S, sa2.S);
int len1 = strlen(sa1.S), len2 = strlen(sa2.S);
sa1.S[len1] = 1;
strcpy(sa1.S+len1+1, sa2.S);
sa1.init(len1+len2+1);
sa2.init(len2);
sa1.getHei();
sa2.getHei();
sa1.initRMQ();
sa2.initRMQ();
LL ans = 0;
for(int i = 1; i < len2; ++i){
LL t1 = sa1.solve(len1+1, i);
LL t2 = sa2.solve(0, i);
LL t3 = t1-t2;
t1 = sa1.solve(len1+1+i, len2-i);
t2 = sa2.solve(i, len2-i);
ans += t3*(t1-t2);
}
printf("%lld\n", ans);
}
return 0;
}
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <queue>
#include <algorithm>
#include <vector>
#include <cstring>
#include <stack>
#include <cctype>
#include <utility>
#include <map>
#include <string>
#include <climits>
#include <set>
#include <string>
#include <sstream>
#include <ctime>
#include <bitset>
#include <iomanip>
#pragma comment(linker, "/STACK:102400000,102400000")
using std::priority_queue;
using std::vector;
using std::swap;
using std::stack;
using std::sort;
using std::max;
using std::min;
using std::pair;
using std::map;
using std::string;
using std::cin;
using std::cout;
using std::set;
using std::queue;
using std::string;
using std::stringstream;
using std::make_pair;
using std::getline;
using std::greater;
using std::endl;
using std::multimap;
using std::deque;
using std::unique;
using std::lower_bound;
using std::random_shuffle;
using std::bitset;
using std::upper_bound;
using std::multiset;
using std::ios;
using std::make_heap;
using std::push_heap;
using std::pop_heap;
typedef long long LL;
typedef unsigned long long ULL;
typedef unsigned UN;
typedef pair<int, int> PAIR;
typedef multimap<int, int> MMAP;
typedef long double LF;
const int MAXN(100010);
const int MAXM(20010);
const int MAXE(2100010);
const int MAXK(6);
const int HSIZE(1313131);
const int SIGMA_SIZE(26);
const int MAXH(19);
const int INFI((INT_MAX-1) >> 1);
const ULL BASE(31);
const LL LIM(1e13);
const int INV(-10000);
const int MOD(1000000007);
const double EPS(1e-7);
const LF PI(acos(-1.0));
template<typename T> inline bool checkmax(T &a, T b){if(b > a) { a = b; return true;} return false;}
template<typename T> inline bool checkmin(T &a, T b){if(b < a) { a = b; return true;} return false;}
template<typename T> inline T ABS(T a){return a < 0? -a: a;}
template<typename T> inline bool EZ(T a){return ABS(a) < EPS;}
/*
template<typename TY, int N>
struct EXKMP{
TY P[N];
int lenp;
int next[N];
void getnext(){
next[0] = lenp;
int k = 1, l = 0, a = 1;
while(k < lenp && P[k] == P[l]){
++k;
++l;
}
next[l] = 1;
int i = 2;
while(i < lenp){
int temp = next[i-a];
if(i+temp < k) next[i] = temp;
else{
checkmax(k, i);
l = k-i;
while(k < lenp && P[k] == P[l]){
++k;
++l;
}
next[i] = l;
a = i;
}
++i;
}
next[lenp] = 0;
}
TY T[N];
int lent;
int extend[N];
void getextend(){
int i, a, p, j(-1);
for(i = 0; i < lent; ++i, --j){
if(j < 0 || i+next[i-a] >= p){
if(j < 0) j = 0, p = i;
while(p < lent && j < lenp && T[p] == P[j]) ++p, ++j;
extend[i] = j, a = i;
}
else
extend[i] = next[i-a];
}
}
};
*/
template<typename TY, int N>
struct EXKMP
{
TY P[N];
int lenp;
int next[N]; //next[i]表示str[i...len-1] 与 str[0...len-1]的最长公共前缀
void getnext()
{
next[0] = lenp;
int k = 1, l = 0, a = 1; //含义: 当前位置, 匹配长度
while(k < lenp && P[k] == P[l])
{
++k;
++l;
}
next[1] = l;
int i = 2;
while(i < lenp)
{
int temp = next[i-a];
if(i+temp < k) next[i] = temp;
else
{
checkmax(k, i);
l = k-i;
while(k < lenp && P[k] == P[l])
{
++k;
++l;
}
next[i] = l;
a = i;
}
++i;
}
next[lenp] = 0;
}
TY T[N];
int lent;
int extend[N];
void getextend()
{
int i, a, p, j(-1);
for(i = 0; i < lent; ++i, --j)
{
if(j < 0 || i+next[i-a] >= p)
{
if(j < 0) j = 0, p = i;
while(p < lent && j < lenp && T[p] == P[j]) ++p, ++j;
extend[i] = j, a = i;
}
else extend[i] = next[i-a];
}
}
};
void rev(char *sp, int len){
int l = 0, r = len-1;
while(l < r){
swap(sp[l], sp[r]);
++l;
--r;
}
}
EXKMP<char, MAXN> exk;
int cnt1[MAXN], cnt2[MAXN];
int main(){
int TC;
scanf("%d", &TC);
while(TC--){
scanf("%s%s", exk.T, exk.P);
exk.lenp = strlen(exk.P);
exk.lent = strlen(exk.T);
exk.getnext();
exk.getextend();
memset(cnt1, 0, sizeof(cnt1[0])*(exk.lenp+1));
for(int i = 0; i < exk.lent; ++i) ++cnt1[exk.extend[i]];
for(int i = exk.lenp-1; i > 0; --i) cnt1[i] += cnt1[i+1];
rev(exk.P, exk.lenp);
rev(exk.T, exk.lent);
exk.getnext();
exk.getextend();
memset(cnt2, 0, sizeof(cnt2[0])*(exk.lenp+1));
for(int i = 0; i < exk.lent; ++i) ++cnt2[exk.extend[i]];
for(int i = exk.lenp-1; i > 0; --i) cnt2[i] += cnt2[i+1];
LL ans = 0;
for(int i = 1; i < exk.lenp; ++i) ans += (LL)cnt1[i]*cnt2[exk.lenp-i];
printf("%lld\n", ans);
}
return 0;
}