1 条题解
-
0
自动搬运
来自洛谷,原作者为

123456xwd
**搬运于
2025-08-24 22:38:47,当前版本为作者最后更新于2025-08-19 21:29:39,作者可能在搬运后再次修改,您可在原文处查看最新版自动搬运只会搬运当前题目点赞数最高的题解,您可前往洛谷题解查看更多
以下是正文
提供简短一点的代码。
其实就是回文树的启发式合并模板题目,时间复杂度为 。
那么我们需要实现回文树的向前插入。
考虑向前插入需要新考虑啥。
对于 ,显然向前向后都一样的使用。
对于 ,表示当前节点的最长回文后缀,但我们现在想要知道最长回文前缀。
不过由于节点 代表的也是一个回文串,那么这两个其实就是一个东西。
那么向前插入本质上和向后插入差不多,唯一需要注意的就是你的代码实现中向前插入时,下标要特殊处理一下,以及此时需要维护前缀最大回文和后缀最大回文的两个节点下标。
且若现在整个串都为回文串,那么会对两个下标都造成影响。
代码中下标从 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; }
- 1
信息
- ID
- 7683
- 时间
- 1000ms
- 内存
- 512MiB
- 难度
- (无)
- 标签
- 递交数
- 0
- 已通过
- 0
- 上传者