BZOJ4044 [Cerc2014] Virus synthesis

神仙题qwq

当时在某校听梁大讲课就没听懂qaq

又研究了一下Claris的题解发现好像还阔以qwq

我们可以很自然地想到回文自动机

我们令f[x]表示回文自动机上的节点x最少需要f[x]个操作

可以发现有这样几种转移

f[x]=len[x](len[x]&1==1)

f[x]=len[x]/2+1 (len[x]&1==0)

f[x]=len[x]/2-len[y]+f[y]+1(y表示x最长的不超过len[x]/2的border:由于是回文串其实就是后缀)

我们可以在回文自动机建立的时候直接找到对于每个x的y

然后接下来用bfs序更新即可

神仙题orz

//Love and Freedom.
#include<cstdio>
#include<cmath>
#include<algorithm>
#include<cstring>
#include<queue>
#define ll long long
#define inf 20021225
#define N 100010
using namespace std;
int id(char c){if(c=='A')return 0;if(c=='T')return 1;if(c=='G')return 2;return 3;}
struct node
{
    int ch[4],len,fail,sz;
    void clear()
    {
        for(int i=0;i<4;i++)    ch[i]=0;
        len=fail=sz=0;
    }
}t[N];
int poi,n,lst,s[N],ls[N],f[N];
void init()
{
    s[0]=-1;
    t[0].len=0; t[1].len=-1;
    t[0].fail=1; t[1].fail=1;
    n=0; poi=lst=1;
}
void extend(int c)
{
    int p=lst; s[++n]=c;
    while(s[n-1-t[p].len]!=s[n])    p=t[p].fail;
    if(!t[p].ch[c])
    {
        int q=++poi; t[q].len=t[p].len+2; int np=t[p].fail;
        while(s[n-1-t[np].len]!=s[n])    np=t[np].fail;
        t[q].fail=t[np].ch[c]; t[p].ch[c]=q;
        if(t[q].len<=2){ls[q]=t[q].fail;}
        else
        {
            ls[q]=ls[p];
            while(s[n-1-t[ls[q]].len]!=s[n]||(t[ls[q]].len+2)*2>t[q].len)
                ls[q]=t[ls[q]].fail;
            ls[q]=t[ls[q]].ch[s[n]];
        }
    }
    lst=t[p].ch[c]; t[lst].sz++;
}
void clear()
{
    for(int i=0;i<=poi;i++)    f[i]=ls[i]=0,t[i].clear();
}
char ch[N]; queue<int> que;
void update(int &x,int y){x=min(x,y);}
int main()
{
    int T; scanf("%d",&T);
    while(T--)
    {
        scanf("%s",ch+1); int len=strlen(ch+1); init();
        for(int i=1;i<=len;i++)    extend(id(ch[i]));
        f[0]=1; int ans=len;
        for(int i=2;i<=poi;i++)
            if(t[i].len&1)    f[i]=t[i].len;
        que.push(0);
        while(!que.empty())
        {
            int x=que.front(); que.pop();
            for(int i=0;i<4;i++) if(t[x].ch[i])
            {
                int y=t[x].ch[i]; f[y]=f[x]+1;
                update(f[y],t[y].len/2-t[ls[y]].len+f[ls[y]]+1);
                update(ans,len-t[y].len+f[y]); que.push(y);
            }
        }
        printf("%d\n",ans); clear();
    }
    return 0;
}
View Code

 

posted @ 2019-06-27 08:35  寒雨微凝  阅读(177)  评论(0编辑  收藏  举报