• CF906E Reverses PAM+border


    题意:

    戳这里

    分析:

    • 暴力:

    对于PAM的DP题目,可能需要将题目转化一下,将原串变为 (s_1t_1s_2t_2dots s_nt_n) ,这样对于一个需要翻转的区间 ([i,j]) 满足 (s_i=t_j,s_{i+1}=t_{j-1}) 即区间 ([i,j]) 在新构造的串上是一个偶回文子串,题目转化为对新串求最小偶回文分割方案,建出SAM暴力DP,转移式 (f[i]=min {f[i],f[j]+1且s[j:i]为回文串}),因为 (PAM) 的结构,所以 (s[j:i])(s[1:i]) 的一个回文后缀所以跳 (fail) 就能找到所有的 (j),复杂度理论上界 (O(n^2))

    • 正解

    由于PAM的树高可以达到(O(n)),所以暴力跳 (fail) 是会被卡的,所以我们需要利用 PAM 的另一个结论,由于串 S 的所有回文后缀排序后可以分为 (O(log n)) 个等差数列,所以我们可以对于每一个等差数列进行转移,复杂度(O(nlog n))

    tip:

    要特判长度为 2 的回文串划分是不需要代价

    代码:

    #include<bits/stdc++.h>
    #define inl inline
    #define reg register
    
    using namespace std;
    
    namespace zzc
    {
        const int maxn = 1e6+5;
        int m,n;
        int f[maxn],whe[maxn],lpos[maxn];
        char ch[maxn],a[maxn],b[maxn];
    
        namespace PAM
        {
            int tot,lst;
            int len[maxn],trans[maxn][26],fail[maxn],slink[maxn],dif[maxn];
    
            inl void init()
            {
                len[0]=0;len[1]=-1;
                fail[0]=1;fail[1]=-1;
                tot=1;lst=0;
            }
    
            inl int get_fail(int x,int l)
            {
                while(ch[l-len[x]-1]!=ch[l]) x=fail[x];
                return x;
            }
    
            inl void insert(int c,int l)
            {
                int p=get_fail(lst,l);
                if(!trans[p][c])
                {
                    int cur=++tot;
                    len[cur]=len[p]+2;
                    int tmp=get_fail(fail[p],l);
                    fail[cur]=trans[tmp][c];
                    trans[p][c]=cur;
                    dif[cur]=len[cur]-len[fail[cur]];
                    if(dif[cur]==dif[fail[cur]]) slink[cur]=slink[fail[cur]];
                    else slink[cur]=fail[cur];
                }
                lst=trans[p][c];
            }
        }
        using namespace PAM;
    
        void work()
        {
            scanf("%s",a+1);scanf("%s",b+1);n=strlen(a+1);
            for(reg int i=1;i<=n;i++) ch[++m]=a[i],ch[++m]=b[i];
            init();for(reg int i=1;i<=m;i++) f[i]=1e9;
            ch[0]=ch[m+1]=100;whe[0]=1;
            for(reg int i=1;i<=m;i++)
            {
                insert(ch[i]-'a',i);
                for(reg int x=lst;x;x=slink[x])
                {
                    whe[x]=i-len[slink[x]]-dif[x];
                    if(dif[fail[x]]==dif[x]&&f[whe[x]]>f[whe[fail[x]]]) whe[x]=whe[fail[x]];
                    if(i%2==0&&f[i]>f[whe[x]]+1) f[i]=f[whe[x]]+1,lpos[i]=whe[x];
                    if(i%2==0&&ch[i]==ch[i-1]&&f[i]>f[i-2]) f[i]=f[i-2],lpos[i]=i-2;
                }
            }
            if(f[m]>=1e9) 
            {
                puts("-1");
                return ;
            }
            printf("%d
    ",f[m]);
            for(reg int x=m;x;x=lpos[x]) if(x-lpos[x]!=2) printf("%d %d
    ",lpos[x]/2+1,x/2);
        }
    }
    
    int main()
    {
        zzc::work();
        return 0;
    }
    
  • 相关阅读:
    DVWA SQL Injection High
    DVWA SQL Injection Medium
    Sagemath在ctf密码学中的使用
    Python杂记
    Elgamal&RSA小结
    攻防世界-密码学-onetimepad
    攻防世界-密码学-sleeping-guard
    攻防世界-密码学-streamgame1
    GACTF2020密码学部分详解
    攻防世界-密码学-xor_game
  • 原文地址:https://www.cnblogs.com/youth518/p/14428641.html
Copyright © 2020-2023  润新知