p.p即回文树结点个数。减去最开始的奇回文根和偶回文根即本质不同回文子串个数
//KX
#include <bits/stdc++.h>
using namespace std;
template<typename T>inline void rd(T&x){
x=0;int f=1;char ch=getchar();
while(ch<'0' ||ch>'9'){ if(ch=='-')f=-1; ch=getchar(); }
while(ch>='0' && ch<='9'){ x=x*10+ch-'0'; ch=getchar(); }
x*=f;
}
typedef long long ll;
typedef double db;
#define ls o*2
#define rs o*2+1
#define pb push_back
const int M = 1e5+7 ;
const int N = 27 ;
struct pam{
int nxt[M][N],fail[M];//在当前状态首尾添加字符的状态,失配跳到的状态
int len[M],S[M],ppos[M];//状态i表示的回文长度,缓存池,状态对应首次出现的位置
int cnt[M],num[M];//状态出现次数,以状态末尾结尾但不包含本条路径的数目
int last,n,p;//上个状态,总长度,当前状态编号
int newnode(int l){
memset(nxt[p],0,sizeof nxt[p]);
cnt[p]=num[p]=0;
len[p]=l;
return p++;
}
void init(){
p=0;
newnode(0);newnode(-1);
last=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,int pos){
c-='a';
S[++n]=c;
int cur=get_fail(last);
if(!nxt[cur][c]){
int now=newnode(len[cur]+2);
ppos[now]=pos;
fail[now]=nxt[get_fail(fail[cur])][c];
nxt[cur][c]=now;
num[now]=num[fail[now]]+1;
}last=nxt[cur][c];cnt[last]++;
}
void Count(){
for(int i=p-1;i>=0;--i)cnt[fail[i]]+=cnt[i];
}
}p;
//p.p-2本质不同回文串的个数
char s[M];
int main()
{
scanf("%s",s);
int len=strlen(s);
p.init();
for(int i=0;i<len;i++)
{
p.add(s[i],i);
printf("%d ",p.p-2);
}
return 0;
}
回文树算法解析
本文深入探讨了回文树(Palindromic Tree)的构建原理及应用,通过实例讲解了如何利用回文树计算字符串中本质不同的回文子串个数。回文树是一种高效的数据结构,用于处理字符串中的回文问题。
1849

被折叠的 条评论
为什么被折叠?



