[CERC2014]Virus synthesis



初始有一个空串,利用下面的操作构造给定串 SS 。

1、串开头或末尾加一个字符

2、串开头或末尾加一个该串的逆串

求最小化操作数, \(|S| \le 10^5\)

可以发现最终的答案必然是先构造出一个偶数的回文串,然后再在回文串的两端把剩下的用操作\(1\)补全

而这个偶数长度的回文串可以通过操作\(2\)得到,最终答案就是这个偶数长度的回文串的构造花费加上剩下来的字符的数量

我们构建回文自动机

我们只关心偶数长度回文串的构造花费,假设自动机上的节点\(x\)的构造花费为\(cost_x\)

存在两种转移:

1.从上一个偶数回文串的两端各加一个字符得到,这个可以在上一个回文串没翻倍之前先在末尾加上一个字符再翻倍,设上一个回文串的构造耗费为\(cost_y\),则\(cost_x=min(cost_x,cost_y+1)\)

2.从上一个长度小于等于当前长度一半的最长回文转移过来,先在上一个回文串的两端补全成当前回文串的一半再翻倍\(cost_x=min(cost_x,cost_y+1+len_x-len_y)\)

//#pragma GCC optimize("O3")
//#pragma comment(linker, "/STACK:1024000000,1024000000")
#include<bits/stdc++.h>
using namespace std;
function<void(void)> ____ = [](){ios_base::sync_with_stdio(false); cin.tie(0); cout.tie(0);};
const int MAXN = 1e5+7;
const int INF = 0x3f3f3f3f;
class PAM{
private:
char s[MAXN];
int len[MAXN],ch[MAXN][4],fail[MAXN][20],last,tot,n,cost[MAXN],f[MAXN];
int calfail(int x, int pos){ while(s[pos]!=s[pos-len[x]-1]) x = fail[x][0]; return x; }
public:
void init(){
memset(ch[0],0,sizeof(ch[0])); memset(ch[1],0,sizeof(ch[1]));
tot = 1; last = 0;
len[0] = 0; len[1] = -1;
fail[0][0] = 1; fail[1][0] = 0;
scanf("%s",s+1); n = strlen(s+1);
for(int i = 1; i <= n; i++){
if(s[i]=='G') s[i] = 'B';
if(s[i]=='T') s[i] = 'D';
}
}
void newnode(){
tot++; cost[tot] = INF;
memset(ch[tot],0,sizeof(ch[tot]));
memset(fail[tot],0,sizeof(fail[tot]));
}
void insert(int pos){
int c = s[pos] - 'A';
int u = calfail(last,pos);
if(!ch[u][c]){
newnode();
len[tot] = len[u] + 2;
fail[tot][0] = ch[calfail(fail[u][0],pos)][c];
for(int i = 1; fail[tot][i-1] > 1; i++) fail[tot][i] = fail[fail[tot][i-1]][i-1];
ch[u][c] = tot;
}
last = ch[u][c];
}
void bfs(){
queue<int> que;
for(int i = 0; i < 4; i++) if(ch[0][i]){
que.push(ch[0][i]);
cost[ch[0][0]] = 2;
}
for(int i = 1; i <= tot; i++) cost[i] = len[i];
while(!que.empty()){
int u = que.front();
que.pop();
int now = u;
for(int i = 19; i >= 0; i--) if(len[fail[now][i]]>len[u]/2) now = fail[now][i];
int half = fail[now][0];
cost[u] = min(cost[u],cost[half]+1+len[u]/2-len[half]);
for(int i = 0; i < 4; i++) if(ch[u][i]){
cost[ch[u][i]] = min(cost[ch[u][i]],cost[u]+1);
que.push(ch[u][i]);
}
}
}
void solve(){
for(int i = 1; i <= n; i++) insert(i);
bfs();
int ret = INF;
for(int i = 2; i <= tot; i++) ret = min(ret,n-len[i]+cost[i]);
printf("%d\n",ret);
}
}pam; void solve(){
pam.init();
pam.solve();
}
int main(){
int T;
for(scanf("%d",&T); T; T--) solve();
return 0;
}

[CERC2014]Virus synthesis【回文自动机+DP】的更多相关文章

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

    bzoj4044/luoguP4762 [Cerc2014]Virus synthesis(回文自动机+dp) bzoj Luogu 你要用ATGC四个字母用两种操作拼出给定的串: 1.将其中一个字符 ...

  2. BZOJ 4044 Luogu P4762 [CERC2014]Virus Synthesis (回文自动机、DP)

    好难啊..根本不会做..基本上是抄Claris... 题目链接: (bzoj)https://www.lydsy.com/JudgeOnline/problem.php?id=4044 (luogu) ...

  3. BZOJ 4044 Virus synthesis (回文自动机+dp)

    题目大意: 你可以在一个串的开头或者末尾加入一个字符,或者把当前整个串$reverse$,然后接在前面或者后面,求达到目标串需要的最少操作次数 对目标串建出$PAM$ 定义$dp[x]$表示当前在回文 ...

  4. luogu P4762 [CERC2014]Virus synthesis (回文自动机)

    大意: 初始有一个空串, 操作(1)在开头或末尾添加一个字符. 操作(2)在开头或末尾添加该串的逆串. 求得到串$S$所需最少操作数. 显然最后一定是由某个偶回文通过添加字符得到的, 那么只需要求出所 ...

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

    4044: [Cerc2014] Virus synthesis Time Limit: 20 Sec  Memory Limit: 128 MB Description Viruses are us ...

  6. bzoj 4044: Virus synthesis 回文自动机

    题目大意: 你要用ATGC四个字母用两种操作拼出给定的串: 将其中一个字符放在已有串开头或者结尾 将已有串复制,然后reverse,再接在已有串的头部或者尾部 一开始已有串为空.求最少操作次数. le ...

  7. bzoj 4044 Virus synthesis - 回文自动机 - 动态规划

    题目传送门 需要高级权限的传送门 题目大意 要求用两种操作拼出一个长度为$n$的只包含'A','T','G','C'的字符串 在当前字符串头或字符串结尾添加一个字符 将当前字符串复制,将复制的串翻转, ...

  8. bzoj2084/luoguP3501 [Poi2010]Antisymmetry(回文自动机+dp)

    bzoj2084/luoguP3501 [Poi2010]Antisymmetry(回文自动机+dp) bzoj Luogu 对于一个01字符串,如果将这个字符串0和1取反后,再将整个串反过来和原串一 ...

  9. 洛谷P4762 [CERC2014]Virus synthesis(回文自动机+dp)

    传送门 回文自动机的好题啊 先建一个回文自动机,然后记$dp[i]$表示转移到$i$节点代表的回文串的最少的需要次数 首先肯定2操作越多越好,经过2操作之后的串必定是一个回文串,所以最后的答案肯定是由 ...

随机推荐

  1. Harbor镜像删除回收?只看这篇

    最近,公司的技术平台,运维的破事儿颇多.Jira无法访问,ES堆内存不足,Jenkins频繁不工作..等等等,让我这个刚入门的小兵抓心脑肝,夜不能寐,关键时刻方恨经验薄弱呀!!一波未平,一波又起,这不 ...

  2. 【ORA】ORA-01756: quoted string not properly terminated

    出现ORA-01756: quoted string not properly terminated 后,查看SQL是否有中文符号 修改为英文的符号,运行正常

  3. AmoebaNet:经费在燃烧,谷歌提出基于aging evolution的神经网络搜索 | AAAI 2019

    论文提出aging evolution,一个锦标赛选择的变种来优化进化算法,在NASNet搜索空间上,对比强化学习和随机搜索,该算法足够简洁,而且能够更快地搜索到更高质量的模型,论文搜索出的Amoeb ...

  4. oracle常见进度查询脚本

    1.查看索引创建进度 /* Formatted on 2019/8/20 下午 05:08:25 (QP5 v5.163.1008.3004) */ SELECT SID, DECODE (total ...

  5. 超精讲-逐例分析CS:LAB2-Bomb!(上)

    0. 环境要求 关于环境已经在lab1里配置过了这里要记得安装gdb 安装命令 sudo yum install gdb 实验的下载地址 http://csapp.cs.cmu.edu/3e/labs ...

  6. 算法模板 - C++ 高精度运算

    C++算法板子 高精度 高精度推荐用python来写,python有大整数,这里写的是关于C++的高精度运算模板 1.高精 * 低精 #include <iostream> #includ ...

  7. 前端开发好帮手,eslint配置全知道

    eslint让人又爱又恨,原因在于它的默认配置非常严格,动则一个小提示就直接报错不给运行.而在开发调试的过程中,我们想时时得到运行效果,它的严格又很烦. 在安装eslint后,我们可以在package ...

  8. TCP三次握手Linux源码解析

    TCP是面向连接的协议.面向连接的传输层协议在原点和重点之间建立了一条虚拟路径,同属于一个报文的所有报文段都沿着这条虚拟路径发送,为整个报文使用一条虚拟路径能够更容易地实施确认过程以及对损伤或者丢失报 ...

  9. 聊聊.net应用程序的Docker镜像

    ​要在容器中运行.net应用程序,你需要在容器镜像中安装.net Framework或.net Core 运行时.这不是你需要自己管理的东西,因为微软提供的Docker镜像已经安装了运行时,你可以使用 ...

  10. 超微服务器重置ipmi登录密码

    超微服务器的ipmi登录密码不对,需要重置但是bios内并没有找到可以设置的选项. 以下是解决办法: 安装IPMITOOLyum install ipmitool -y 执行以下命令加载模块:modp ...