Palindromic Tree——回文树【处理一类回文串问题的强力工具】
num[i]:i表示的回文字符串中有多少个本质不同的字符串(包括本身)
cnt[i]:i表示的回文字符串在整个字符串中出现了多少次
HDU3948 The Number of Palindromes
求本质不同的回文子串个数
#include<bits/stdc++.h>
using namespace std;
const int MAX=1e5+5;
struct Trie
{
static const int MAXN=26;
int nxt[MAX][MAXN],f[MAX],cnt[MAX],num[MAX],len[MAX],c[MAX],last,n,L;
int newnode(int x)
{
for(int i=0;i<MAXN;++i) nxt[L][i]=0;
cnt[L]=num[L]=0;len[L]=x;return L++;
}
void init()
{
L=0;newnode(0);newnode(-1);
last=0;n=0;c[n]=-1;f[0]=1;
}
int getf(int x)
{
while(c[n-len[x]-1]!=c[n]) x=f[x];
return x;
}
void add(int x)
{
x-='a';c[++n]=x;
int cur=getf(last);
if(!nxt[cur][x])
{
int now=newnode(len[cur]+2);
f[now]=nxt[getf(f[cur])][x];
nxt[cur][x]=now;
num[now]=num[f[now]]+1;
}
++cnt[last=nxt[cur][x]];
}
void count()
{
for(int i=L-1;i>=2;--i) cnt[f[i]]+=cnt[i];
}
}PT;
char s[MAX];
int t;
int main()
{
int tc=0;
scanf("%d",&t);
while(t--)
{
PT.init();
scanf("%s",s);
int l=strlen(s);
for(int i=0;i<l;++i) PT.add(s[i]);
printf("Case #%d: %d\n",++tc,PT.L-2);//2个根节点
}
return 0;
}
max(cnt[i]*len[i])
#include<bits/stdc++.h>
using namespace std;
const int MAX=3e5+5;
struct Trie
{
static const int MAXN=26;
int nxt[MAX][MAXN],f[MAX],cnt[MAX],num[MAX],len[MAX],c[MAX],last,n,L;
int newnode(int x)
{
for(int i=0;i<MAXN;++i) nxt[L][i]=0;
cnt[L]=num[L]=0;len[L]=x;return L++;
}
void init()
{
L=0;newnode(0);newnode(-1);
last=0;n=0;c[n]=-1;f[0]=1;
}
int getf(int x)
{
while(c[n-len[x]-1]!=c[n]) x=f[x];
return x;
}
void add(int x)
{
x-='a';c[++n]=x;
int cur=getf(last);
if(!nxt[cur][x])
{
int now=newnode(len[cur]+2);
f[now]=nxt[getf(f[cur])][x];
nxt[cur][x]=now;
num[now]=num[f[now]]+1;
}
++cnt[last=nxt[cur][x]];
}
void count(){for(int i=L-1;i>=2;--i) cnt[f[i]]+=cnt[i];}
}PT;
char s[MAX];
int main()
{
while(~scanf("%s",s))
{
PT.init();
int l=strlen(s);
for(int i=0;i<l;++i) PT.add(s[i]);
PT.count();
long long ans=0;
for(int i=PT.L-1;i>=2;--i) ans=max(ans,(long long)1*PT.cnt[i]*PT.len[i]);
printf("%lld\n",ans);
}
return 0;
}
统计所有回文串的个数 -cnt之和 -(也可以沿着last统计num之和)
#include<bits/stdc++.h>
using namespace std;
const int MAX=8e5+5;
long long ans;
struct Trie
{
static const int MAXN=26;
int nxt[MAX][MAXN],f[MAX],cnt[MAX],num[MAX],len[MAX],c[MAX],last,n,L;
int newnode(int x)
{
for(int i=0;i<MAXN;++i) nxt[L][i]=0;
cnt[L]=num[L]=0;len[L]=x;return L++;
}
void init()
{
L=0;newnode(0);newnode(-1);
last=0;n=0;c[n]=-1;f[0]=1;
}
int getf(int x)
{
while(c[n-len[x]-1]!=c[n]) x=f[x];
return x;
}
void add(int x)
{
x-='a';c[++n]=x;
int cur=getf(last);
if(!nxt[cur][x])
{
int now=newnode(len[cur]+2);
f[now]=nxt[getf(f[cur])][x];
nxt[cur][x]=now;
num[now]=num[f[now]]+1;
}
++cnt[last=nxt[cur][x]];
}
void count(){for(int i=L-1;i>=2;--i) cnt[f[i]]+=cnt[i];}
}PT;
char s[MAX];
int main()
{
while(~scanf("%s",s))
{
PT.init();ans=0;
int l=strlen(s);
for(int i=0;i<l;++i) PT.add(s[i]);
PT.count();
for(int i=2;i<PT.L;++i) ans+=PT.cnt[i];
printf("%lld\n",ans);
}
return 0;
}