博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
洛谷P4762 [CERC2014]Virus synthesis(回文自动机+dp)
阅读量:6195 次
发布时间:2019-06-21

本文共 2357 字,大约阅读时间需要 7 分钟。

 

回文自动机的好题啊

先建一个回文自动机,然后记$dp[i]$表示转移到$i$节点代表的回文串的最少的需要次数

首先肯定2操作越多越好,经过2操作之后的串必定是一个回文串,所以最后的答案肯定是由一个回文串+不断暴力添加得来,那么答案就是$min(ans,dp[i]+n-len[i])$

然后对于一个串$i$,如果它在前面和后面加上一个字母可以形成回文串$j$,则$dp[j]=dp[i]+1$

为啥嘞?我们可以假设在形成$i$的之前一步把这个字母加上去,执行2操作后就可以变成$j$了

然后我们可以fail指针找到最长的回文串$x$满足$len[x]<=len[i]/2$,那么$dp[i]=min(dp[i],dp[x]+1+len[i]/2-len[x])$(先暴力填好一半,剩下的用2操作)

然后可以用队列记录状态,保证转移至有序的

至于怎么找$x$,我们可以直接在建自动机的时候顺便求出来,就是多跳几次。这个看代码好了

1 //minamoto 2 #include
3 #include
4 template
inline bool cmin(T&a,const T&b){
return a>b?a=b,1:0;} 5 const int N=2e5+5,M=5; 6 char s[N];int dp[N],len[N],fail[N],ch[N][M]; 7 int trans[N],last,p,q,str[N],tot,ans,n,qu[N]; 8 int val[105]; 9 inline int newnode(int x){10 len[++tot]=x;memset(ch[tot],0,sizeof(ch[tot])*5);return tot;11 }12 inline int getfail(int x,int n){13 while(s[n-len[x]-1]!=s[n]) x=fail[x];return x;14 }15 inline void init(){16 val['A']=0,val['T']=1,val['C']=2,val['G']=3;17 s[0]=-1,fail[0]=1,last=0;18 len[0]=0,len[1]=-1,tot=1;19 memset(ch[0],0,sizeof(int)*5),memset(ch[1],0,sizeof(int)*5);20 }21 void ins(int c,int i){22 p=getfail(last,i);23 if(!ch[p][c]){24 q=newnode(len[p]+2);25 fail[q]=ch[getfail(fail[p],i)][c];26 ch[p][c]=q;27 if(len[q]<=2) trans[q]=fail[q];28 else{29 int tmp=trans[p];30 while(s[i-1-len[tmp]]!=s[i]||(len[tmp]+2)*2>len[q]) tmp=fail[tmp];31 trans[q]=ch[tmp][c];32 }33 }34 last=ch[p][c];35 // printf("%d\n",last);36 }37 int main(){38 // freopen("testdata.in","r",stdin);39 int T;scanf("%d",&T);40 while(T--){41 scanf("%s",s+1);42 init(),ans=n=strlen(s+1);43 for(int i=1;i<=n;++i) ins(val[s[i]],i);44 for(int i=2;i<=tot;++i) dp[i]=len[i];45 int h=1,t=0;qu[++t]=0,dp[0]=1;46 while(h<=t){47 int u=qu[h++];48 for(int i=0;i<4;++i){49 int x=ch[u][i];50 if(!x) continue;51 dp[x]=dp[u]+1;52 int y=trans[x];53 cmin(dp[x],dp[y]+1+len[x]/2-len[y]);54 cmin(ans,dp[x]+n-len[x]);55 qu[++t]=x;56 }57 }58 printf("%d\n",ans);59 }60 return 0;61 }

 

转载于:https://www.cnblogs.com/bztMinamoto/p/9630381.html

你可能感兴趣的文章
Android应用程序消息处理机制(Looper、Handler)分析(4)
查看>>
C++ 类成员的构造和析构顺序
查看>>
将String转化成Stream,将Stream转换成String
查看>>
POJ-1011 Sticks
查看>>
swat主流域文件(file.cio)参数详解——引自http://blog.sciencenet.cn/blog-922140-710636.html...
查看>>
支付宝接口错误:您使用的私钥格式错误,请检查RSA私钥配置,charset = utf-8
查看>>
娱乐一下:汤姆君的大转盘算法(搞笑版)
查看>>
java路径Java开发中获得非Web项目的当前项目路径
查看>>
(喷血分享)利用.NET生成数据库表的创建脚本,类似SqlServer编写表的CREATE语句...
查看>>
[译] 为用户提供安全可靠的体验
查看>>
卷积神经网络—基本部件(2)
查看>>
Android 系统开发_四大组件篇 -- 探讨 Activity 的生命周期
查看>>
各个大厂裁员情况,已经慌的一B
查看>>
php.类与对象
查看>>
想入门数据科学领域?明确方向更重要
查看>>
【速记】借助ES6的模版字符串,在不用Babel插件的情况下实现一个轻量级类JSX功能...
查看>>
PHP算法之四大基础算法
查看>>
JavaScript常用数组操作方法,包含ES6方法
查看>>
从0开始用python写一个命令行小游戏(六)
查看>>
「Do.003」 adb无线连接Android设备
查看>>