1 条题解

  • 0
    @ 2025-8-24 22:38:47

    自动搬运

    查看原文

    来自洛谷,原作者为

    avatar 123456xwd
    **

    搬运于2025-08-24 22:38:47,当前版本为作者最后更新于2025-08-19 21:29:39,作者可能在搬运后再次修改,您可在原文处查看最新版

    自动搬运只会搬运当前题目点赞数最高的题解,您可前往洛谷题解查看更多

    以下是正文


    提供简短一点的代码。

    其实就是回文树的启发式合并模板题目,时间复杂度为 O(nlogn)\mathcal{O}(n\log n)

    那么我们需要实现回文树的向前插入。

    考虑向前插入需要新考虑啥。

    对于 chu,cch_{u,c},显然向前向后都一样的使用。

    对于 failufail_u,表示当前节点的最长回文后缀,但我们现在想要知道最长回文前缀。

    不过由于节点 uu 代表的也是一个回文串,那么这两个其实就是一个东西。

    那么向前插入本质上和向后插入差不多,唯一需要注意的就是你的代码实现中向前插入时,下标要特殊处理一下,以及此时需要维护前缀最大回文和后缀最大回文的两个节点下标。

    且若现在整个串都为回文串,那么会对两个下标都造成影响。

    代码中下标从 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
    上传者