洛谷P4762 [CERC2014]Virus synthesis(回文自动机+dp)
回文自动机的好题啊
先建一个回文自动机,然后记$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$,我们可以直接在建自动机的时候顺便求出来,就是多跳几次。这个看代码好了
//minamoto
#include<cstring>
#include<cstdio>
template<class T>inline bool cmin(T&a,const T&b){return a>b?a=b,:;}
const int N=2e5+,M=;
char s[N];int dp[N],len[N],fail[N],ch[N][M];
int trans[N],last,p,q,str[N],tot,ans,n,qu[N];
int val[];
inline int newnode(int x){
len[++tot]=x;memset(ch[tot],,sizeof(ch[tot])*);return tot;
}
inline int getfail(int x,int n){
while(s[n-len[x]-]!=s[n]) x=fail[x];return x;
}
inline void init(){
val['A']=,val['T']=,val['C']=,val['G']=;
s[]=-,fail[]=,last=;
len[]=,len[]=-,tot=;
memset(ch[],,sizeof(int)*),memset(ch[],,sizeof(int)*);
}
void ins(int c,int i){
p=getfail(last,i);
if(!ch[p][c]){
q=newnode(len[p]+);
fail[q]=ch[getfail(fail[p],i)][c];
ch[p][c]=q;
if(len[q]<=) trans[q]=fail[q];
else{
int tmp=trans[p];
while(s[i--len[tmp]]!=s[i]||(len[tmp]+)*>len[q]) tmp=fail[tmp];
trans[q]=ch[tmp][c];
}
}
last=ch[p][c];
// printf("%d\n",last);
}
int main(){
// freopen("testdata.in","r",stdin);
int T;scanf("%d",&T);
while(T--){
scanf("%s",s+);
init(),ans=n=strlen(s+);
for(int i=;i<=n;++i) ins(val[s[i]],i);
for(int i=;i<=tot;++i) dp[i]=len[i];
int h=,t=;qu[++t]=,dp[]=;
while(h<=t){
int u=qu[h++];
for(int i=;i<;++i){
int x=ch[u][i];
if(!x) continue;
dp[x]=dp[u]+;
int y=trans[x];
cmin(dp[x],dp[y]++len[x]/-len[y]);
cmin(ans,dp[x]+n-len[x]);
qu[++t]=x;
}
}
printf("%d\n",ans);
}
return ;
}
洛谷P4762 [CERC2014]Virus synthesis(回文自动机+dp)的更多相关文章
- bzoj4044/luoguP4762 [Cerc2014]Virus synthesis(回文自动机+dp)
bzoj4044/luoguP4762 [Cerc2014]Virus synthesis(回文自动机+dp) bzoj Luogu 你要用ATGC四个字母用两种操作拼出给定的串: 1.将其中一个字符 ...
- BZOJ 4044 Luogu P4762 [CERC2014]Virus Synthesis (回文自动机、DP)
好难啊..根本不会做..基本上是抄Claris... 题目链接: (bzoj)https://www.lydsy.com/JudgeOnline/problem.php?id=4044 (luogu) ...
- luogu P4762 [CERC2014]Virus synthesis (回文自动机)
大意: 初始有一个空串, 操作(1)在开头或末尾添加一个字符. 操作(2)在开头或末尾添加该串的逆串. 求得到串$S$所需最少操作数. 显然最后一定是由某个偶回文通过添加字符得到的, 那么只需要求出所 ...
- BZOJ 4044 Virus synthesis (回文自动机+dp)
题目大意: 你可以在一个串的开头或者末尾加入一个字符,或者把当前整个串$reverse$,然后接在前面或者后面,求达到目标串需要的最少操作次数 对目标串建出$PAM$ 定义$dp[x]$表示当前在回文 ...
- [BZOJ4044]Virus synthesis 回文自动机的DP
4044: [Cerc2014] Virus synthesis Time Limit: 20 Sec Memory Limit: 128 MB Description Viruses are us ...
- bzoj 4044: Virus synthesis 回文自动机
题目大意: 你要用ATGC四个字母用两种操作拼出给定的串: 将其中一个字符放在已有串开头或者结尾 将已有串复制,然后reverse,再接在已有串的头部或者尾部 一开始已有串为空.求最少操作次数. le ...
- bzoj 4044 Virus synthesis - 回文自动机 - 动态规划
题目传送门 需要高级权限的传送门 题目大意 要求用两种操作拼出一个长度为$n$的只包含'A','T','G','C'的字符串 在当前字符串头或字符串结尾添加一个字符 将当前字符串复制,将复制的串翻转, ...
- bzoj2084/luoguP3501 [Poi2010]Antisymmetry(回文自动机+dp)
bzoj2084/luoguP3501 [Poi2010]Antisymmetry(回文自动机+dp) bzoj Luogu 对于一个01字符串,如果将这个字符串0和1取反后,再将整个串反过来和原串一 ...
- [CERC2014]Virus synthesis【回文自动机+DP】
[CERC2014]Virus synthesis 初始有一个空串,利用下面的操作构造给定串 SS . 1.串开头或末尾加一个字符 2.串开头或末尾加一个该串的逆串 求最小化操作数, \(|S| \l ...
随机推荐
- 3.1 第一个场景 HelloWorldScene
HelloWorldScene.h #ifndef __HELLOWORLD_SCENE_H__ #define __HELLOWORLD_SCENE_H__ #include "cocos ...
- [原]NYOJ-开灯问题-77
大学生程序代写 //http://acm.nyist.net/JudgeOnline/problem.php?pid=77 /*题目77题目信息运行结果本题排行讨论区开灯问题 时间限制:3000 ms ...
- freeMarker(一)——freeMarker简介
学习笔记,选自freeMarker中文文档,译自 Email: ddekany at users.sourceforge.net FreeMarker简介: FreeMarker 是一款 模板引擎: ...
- [Codeforces 204E] Little Elephant and Strings
[题目链接] https://codeforces.com/contest/204/problem/E [算法] 首先构建广义后缀自动机 对于自动机上的每个节点 , 维护一棵平衡树存储所有它所匹配的字 ...
- HTML DOM setTimeout() 方法
转自:http://www.w3school.com.cn/jsref/met_win_settimeout.asp 1.setTimeout() 方法用于在指定的毫秒数后调用函数或计算表达式. &l ...
- 0009_if控制语句
1.if 条件: (判断相等一定注意要用 == 而不是 =) 代码块 else: 代码块 2.if 条件一: 代码块 elif 条件二: 代码块 elif 条件三 ...
- 写一个c程序辨别系统是大端or小端字节序
字节序有两种表示方法:大端字节序(big ending),小端字节序(little ending) 看一个unsigned short 数据,它占2个字节,给它赋值0x1234.若采用的大端字节序, ...
- github 分支操作
1.查看分支 1.查看本地分支 使用git branch命令,如下: $ git branch * master *标识的是你当前所在的分支. 2.查看远程分支 命令如下: git branch -r ...
- Could not get lock /var/lib/dpkg/lock - open 解决方法
无法获得锁 /var/lib/dpkg/lock E: Could not get lock /var/lib/dpkg/lock - open (11 Resource temporarily un ...
- 哪个U盘启动工具能安装红帽系统,
安装红帽子,不要使用windows系统下的PE启动盘,两者引导方式不一样,不通用的.正确的方法是网上下载红帽子的ISO镜像文件后,用UltraISO这个工具写入优盘或者光盘,得到的系统盘才可以启动电脑 ...