题解:P8406 [COCI 2021/2022 #6] Palindromi
提供简短一点的代码。
其实就是回文树的启发式合并模板题目,时间复杂度为
那么我们需要实现回文树的向前插入。
考虑向前插入需要新考虑啥。
对于
对于
不过由于节点
那么向前插入本质上和向后插入差不多,唯一需要注意的就是你的代码实现中向前插入时,下标要特殊处理一下,以及此时需要维护前缀最大回文和后缀最大回文的两个节点下标。
且若现在整个串都为回文串,那么会对两个下标都造成影响。
代码中下标从 0 开始,细节有点多。
#include<bits/stdc++.h>
#define ull unsigned long long
#define ll long long
#define p_b push_back
#define m_p make_pair
#define pii pair<int,int>
#define fi first
#define se second
#define ls k<<1
#define rs k<<1|1
#define mid ((l+r)>>1)
#define gcd __gcd
#define lowbit(x) (x&(-x))
using namespace std;
int rd(){
int x=0,f=1; char ch=getchar();
for(;ch<'0'||ch>'9';ch=getchar())if (ch=='-') f=-1;
for(;ch>='0'&&ch<='9';ch=getchar())x=(x<<1)+(x<<3)+(ch^48);
return x*f;
}
void write(int x){
if(x>9) write(x/10);
putchar('0'+x%10);
}
const int N=1e5+5,M=N*19,INF=0x3f3f3f3f;
struct pam{
#define w(x) (op?sz-(x):(x))
struct node{int ch[2],len,fail;}tmp;
vector<node> a;int laspre,lassuf,ans;
deque<int> s;
int New(int len,int fail){tmp.len=len,tmp.fail=fail;a.p_b(tmp);return a.size()-1;}
pam(){New(0,1);New(-1,1);laspre=lassuf=1;}
void insert(int c,int op){
if(!op)s.p_b(c);
else s.push_front(c);
int i=s.size()-1,sz=s.size()-1;
int &las=op?laspre:lassuf;
while(i-a[las].len-1<0||s[w(i)]!=s[w(i-a[las].len-1)])las=a[las].fail;
if(a[las].ch[c]) las=a[las].ch[c];
else{
int tp=a[las].fail;
while(i-a[tp].len-1<0||s[w(i)]!=s[w(i-a[tp].len-1)]) tp=a[tp].fail;
int u=New(2+a[las].len,a[tp].ch[c]);
a[las].ch[c]=u;las=u;ans++;
if(a[las].len==s.size())laspre=lassuf=u;
}
}
}T[N];
int fa[N],n;
int find(int u){
if(fa[u]==u) return u;
return fa[u]=find(fa[u]);
}
int main(){
n=rd();
for(int i=1;i<=n;i++){
char ch=getchar();while(ch!='0'&&ch!='1')ch=getchar();
T[i].insert(ch-'0',0);fa[i]=i;
}
for(int i=1;i<n;i++){
int u=rd(),v=rd();
u=find(u),v=find(v);
if(T[v].s.size()<=T[u].s.size()){
int sz=T[v].s.size();
for(int i=0;i<sz;i++) T[u].insert(T[v].s[i],0);
fa[v]=u;printf("%d\n",T[u].ans);
}
else{
int sz=T[u].s.size();
for(int i=sz-1;i>=0;i--) T[v].insert(T[u].s[i],1);
fa[u]=v;printf("%d\n",T[v].ans);
}
}
return 0;
}