题目链接:https://vjudge.net/problem/UVALive-7041
题意:求两个串的公共回文串的个数。
解法:回文树。回文树学习资料:http://blog.csdn.net/u013368721/article/details/42100363
然后这题就成为了裸题。从0和1两个根节点DFS下去,如果两个相同的节点同时存在就统计答案。
#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
const int maxn = 200010;
const int maxs = 26;
struct Palindromic_Tree{
int next[maxn][maxs];
int fail[maxn];
int cnt[maxn];
int num[maxn];
int len[maxn];
int S[maxn];
int last;
int n;
int p;
int newnode(int l){
for(int i=0; i<maxs; i++) next[p][i] = 0;
cnt[p] = 0;
num[p] = 0;
len[p] = l;
return p++;
}
void init(){
p = 0;
newnode(0);
newnode(-1);
last = 0;
n = 0;
S[n] = -1;
fail[0] = 1;
}
int get_fail(int x){
while(S[n-len[x]-1] != S[n]) x = fail[x];
return x;
}
void add(int c){
c -= 'a';
S[++n] = c;
int cur = get_fail(last);
if(!next[cur][c]){
int now = newnode(len[cur]+2);
fail[now] = next[get_fail(fail[cur])][c];
next[cur][c] = now;
num[now] = num[fail[now]]+1;
}
last = next[cur][c];
cnt[last]++;
}
void count(){
for(int i=p-1; i>=0; i--) cnt[fail[i]] += cnt[i];
}
};
Palindromic_Tree T1, T2;
char s1[maxn], s2[maxn];
int n1, n2;
LL ans;
void dfs(int u, int v){
for(int i=0; i<maxs; i++){
int x = T1.next[u][i], y = T2.next[v][i];
if(x && y){
ans += (LL)T1.cnt[x]*T2.cnt[y];
dfs(x, y);
}
}
}
int main()
{
int T, ks = 0;
scanf("%d", &T);
while(T--)
{
printf("Case #%d: ", ++ks);
ans = 0;
T1.init();
T2.init();
scanf("%s%s", s1, s2);
n1 = strlen(s1);
n2 = strlen(s2);
for(int i=0; i<n1; i++) T1.add(s1[i]);
for(int i=0; i<n2; i++) T2.add(s2[i]);
T1.count();
T2.count();
dfs(0, 0);
dfs(1, 1);
printf("%lld\n", ans);
}
return 0;
}