1 条题解

  • 0
    @ 2025-8-24 22:10:42

    自动搬运

    查看原文

    来自洛谷,原作者为

    avatar 无意识躺枪人
    是OwenOwl的小迷妹 | cdqz最菜OIer

    搬运于2025-08-24 22:10:42,当前版本为作者最后更新于2019-06-14 14:57:31,作者可能在搬运后再次修改,您可在原文处查看最新版

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

    以下是正文


    Q1Q1:我们该选择什么算法?

    首先看到题目的回文串 ,你的想法是不是回文自动机

    然而略加思索,回文自动机找的是回文串最后一个位置,而这道题的关键在于回文串中心位置,所以我们可以用Manacher

    研究一下样例,会发现回文串的扩展符合Manacher扩展方式(可以对着数据模拟一下)

    Q2Q2:然后如何做呢?

    我们都知道,最多有nn个本质不同的回文串,因此当我们扩展到f[i]f[i]时,已经有了ii种回文串。

    然后?暴力扩展啊

    就这样,我们扩展出了一个全新的回文串,这个回文串的基础是之前Manacher的回文串

    这个回文串的基础

    一个回文串必须由上一个回文串发展而来,你应该马上敏感地想到—— 拓扑排序

    就这样,这里扩展出的回文串构成了一个拓扑序

    Q3Q3:然后是hash吗

    Hash当然是很常见的选择

    然而 单哈容易挂掉,双哈码量有些大……

    因此,我们可以用pbds中hash探测法

    点击进入日报详细学习

    O(N)O(N)的复杂度完成字符串类型的map(其实并不是真正的map,但你可以这么理解),码量小,还快得一批……

    这样你就可以做这道题了

    关键代码:

    #include<bits/stdc++.h>
    #include<ext/pb_ds/assoc_container.hpp>
    #define N 3000005
    #define ull unsigned long long
    #define seed1 151
    #define seed2 149
    #define mod 19260817
    #define mem(x) memset(x,0,sizeof(x))
    
    void manacher()
    {
        int i,len;
        len=1;
        a[0]='$';a[1]='#';
        for(register int i=1;i<=n;i++) {a[++len]=c[i];a[++len]='#';}
        a[len+1]='\0';int maxn=0,id=0,lasta=0;
        for(i=1;i<=len;i++)
        {
            if(maxn>i) p[i]=min(maxn-i,p[(id<<1)-i]);
            else p[i]=1;
            if(p[i]==1)lasta=0;
            else lasta=Map[change3(((i-p[i])>>1)+1,(i+p[i]-1)>>1)];
            while(a[i+p[i]]==a[i-p[i]])
            {
                p[i]++;
                int& temp=Map[change3(((i-p[i])>>1)+1,(i+p[i]-1)>>1)];
                if(!temp){temp=++tot;fa[tot]=lasta;sum[tot]=0;}
                lasta=temp;
            }
            sum[lasta]^=(i>>1)-1;
            if(i+p[i]>maxn){maxn=i+p[i];id=i;}
        }
    }
    
    void work()
    {
        now1[0]=1;hash1[0]=0;
        for(register int i=1;i<=n;++i)
        {
            now1[i]=now1[i-1]*seed1%mod;
            hash1[i]=(hash1[i-1]*seed1+c[i])%mod;
        }
        now2[0]=1;hash2[0]=0;
        for(register int i=1;i<=n;++i)
        {
            now2[i]=now2[i-1]*seed2%mod;
            hash2[i]=(hash2[i-1]*seed2+c[i])%mod;
        }
        manacher();
    }
    

    最后,祝各位AC愉快

    • 1

    信息

    ID
    4413
    时间
    1000ms
    内存
    128MiB
    难度
    6
    标签
    (无)
    递交数
    0
    已通过
    0
    上传者