bzoj 4044: [Cerc2014] Virus synthesis回文自动机+dp
Posted lokiii
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了bzoj 4044: [Cerc2014] Virus synthesis回文自动机+dp相关的知识,希望对你有一定的参考价值。
建回文自动机,注意到一个回文串是可以通过一个长度小于等于这个串长度的一半的回文串添上一些字符然后复制得到的,也就是在自动机上向fa走,相当于treedp
每次都走显然会T,记录一个up,指向祖先中最下长度符合要求的回文后缀,这样每次找最多跳一次,所以是O(n)的,还有child的清空动态的做,也就是新建一个点清空一个点
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
const int N=100005;
int T,n,ch[N][5],fa[N],up[N],dis[N],f[N],con,la,mp[205],ans;
char s[N];
void clr(int x)
{
ch[x][0]=ch[x][1]=ch[x][2]=ch[x][3]=0;
}
void ins(int c,int w)
{
int p=la;
for(;s[w-1-dis[p]]!=s[w];p=fa[p]);
if(!ch[p][c])
{
int cur=++con,q=fa[p];
dis[cur]=f[cur]=dis[p]+2,clr(cur);
for(;s[w-dis[q]-1]!=s[w];q=fa[q]);
fa[cur]=ch[q][c];
if(dis[cur]<=2)
up[cur]=fa[cur];
else
{
q=up[p];
for(;s[w-dis[q]-1]!=s[w]||2*(dis[q]+2)>dis[cur];q=fa[q]);
up[cur]=ch[q][c];
}
ch[p][c]=cur;
if((dis[cur]&1)==0)
{
f[cur]=min(f[cur],f[up[cur]]+(dis[cur]/2-dis[up[cur]])+1);
if(p>=2)
f[cur]=min(f[cur],f[p]+1);
}
else
f[cur]=min(f[cur],min(dis[cur]-dis[fa[cur]]+f[fa[cur]],f[p]+2));
}
la=ch[p][c];
}
int main()
{
scanf("%d",&T);
mp[‘A‘]=0,mp[‘T‘]=1,mp[‘G‘]=2,mp[‘C‘]=3;
while(T--)
{
scanf("%s",s+1);
n=strlen(s+1);
ans=n,con=1,la=0,dis[0]=0,dis[1]=-1,fa[0]=1,s[0]=-1;
clr(0),clr(1);
for(int i=1;i<=n;i++)
ins(mp[s[i]],i);
for(int i=2;i<=con;i++)
ans=min(ans,n-dis[i]+f[i]);
printf("%d
",ans);
}
return 0;
}
以上是关于bzoj 4044: [Cerc2014] Virus synthesis回文自动机+dp的主要内容,如果未能解决你的问题,请参考以下文章
bzoj4044/luoguP4762 [Cerc2014]Virus synthesis(回文自动机+dp)
[BZOJ4044]Virus synthesis 回文自动机的DP
bzoj 3928: [Cerc2014] Outer space invaders