P4762 [CERC2014]Virus synthesis

Posted nofind

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了P4762 [CERC2014]Virus synthesis相关的知识,希望对你有一定的参考价值。

题意

真是道回文自动机好题。

首先考虑答案必定是一个回文串+剩余部分的形式,因此可以建出回文自动机,之后考虑每个长度为偶数的回文串。

对于一个长度为偶数的回文串,设它在回文自动机上对应的节点为(x),我们对于每个(x)求出(trans_x)表示x的最长后缀回文串,满足(len_{trans_x}leqslant len_x/2)

之后设(f_x)表示(x)拼成(x)这个串的最小代价,我们从(0)(偶根)出发进行(bfs),中途计算(f_x)

对于(f_x)
初值肯定是自身长度(f_x=len_x)
如果存在一条边((x,y)),那么(f_y=f_x+1),因为我们可以在拼(x)时还没进行(2)操作时向(x)后面填一个字符,使其进行(2)操作后变为(y)
同时(f_x=min(f_x,f_{trans_x}+1+lem_x/2-len_{trans_x})),即我们可以从(trans_x)变过来。

对于每个(x),它对答案的贡献是(n-len_x+f_x)(n)是字符串长度。

code:

#include<bits/stdc++.h>
using namespace std;
const int maxn=1e5+10;
const int inf=1e9;
int T,n,tot,last,ans;
int fail[maxn],len[maxn],trans[maxn],f[maxn];
int ch[maxn][5];
char s[maxn];
inline int change(char c)
{
    if(c=='A')return 1;
    if(c=='G')return 2;
    if(c=='C')return 3;
    if(c=='T')return 4;
    return 2333;
}
inline void init()
{
    for(int i=0;i<=tot;i++)
        for(int j=1;j<=4;j++)
            ch[i][j]=0;
    fail[0]=1;len[1]=-1;
    tot=1;last=0;
}
inline int getfail(int x,int pos)
{
    while(s[pos-len[x]-1]!=s[pos])x=fail[x];
    return x;
}
inline void add(int c,int pos)
{
    int p=getfail(last,pos);
    if(!ch[p][c])
    {
        int q=++tot,tmp;len[q]=len[p]+2;
        tmp=getfail(fail[p],pos);
        fail[q]=ch[tmp][c];ch[p][c]=q;
        if(len[q]<=2)trans[q]=fail[q];
        else  
        {
            tmp=trans[p];
            while(s[pos-len[tmp]-1]!=s[pos]||((len[tmp]+2)<<1)>len[q])tmp=fail[tmp];
            trans[q]=ch[tmp][c];
        }
    }
    last=ch[p][c];
}
inline void solve()
{
    queue<int>q;
    for(int i=2;i<=tot;i++)f[i]=len[i];
    for(int i=1;i<=4;i++)if(ch[0][i])q.push(ch[0][i]);
    while(!q.empty())
    {
        int x=q.front();q.pop();
        f[x]=min(f[x],f[trans[x]]+1+len[x]/2-len[trans[x]]);
        ans=min(ans,n-len[x]+f[x]);
        for(int i=1;i<=4;i++)
        {
            if(!ch[x][i])continue;
            int y=ch[x][i];
            f[y]=min(f[y],f[x]+1);
            q.push(y);
        }
    }
}
int main()
{
    scanf("%d",&T);
    while(T--)
    {
        scanf("%s",s+1);n=strlen(s+1);
        s[0]='#';
        init();
        for(int i=1;i<=n;i++)add(change(s[i]),i);
        ans=n;solve();
        printf("%d
",ans);
    }
    return 0;   
}

以上是关于P4762 [CERC2014]Virus synthesis的主要内容,如果未能解决你的问题,请参考以下文章

Cerc2014 Virus synthesis

bzoj4044 [Cerc2014] Virus synthesis

bzoj 4044: [Cerc2014] Virus synthesis回文自动机+dp

bzoj4044/luoguP4762 [Cerc2014]Virus synthesis(回文自动机+dp)

[BZOJ4044]Virus synthesis 回文自动机的DP

[Cerc2014] Vocabulary