[CERC2014]Virus synthesis【回文自动机+DP】
[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】的更多相关文章
- 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) ...
- BZOJ 4044 Virus synthesis (回文自动机+dp)
题目大意: 你可以在一个串的开头或者末尾加入一个字符,或者把当前整个串$reverse$,然后接在前面或者后面,求达到目标串需要的最少操作次数 对目标串建出$PAM$ 定义$dp[x]$表示当前在回文 ...
- luogu P4762 [CERC2014]Virus synthesis (回文自动机)
大意: 初始有一个空串, 操作(1)在开头或末尾添加一个字符. 操作(2)在开头或末尾添加该串的逆串. 求得到串$S$所需最少操作数. 显然最后一定是由某个偶回文通过添加字符得到的, 那么只需要求出所 ...
- [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取反后,再将整个串反过来和原串一 ...
- 洛谷P4762 [CERC2014]Virus synthesis(回文自动机+dp)
传送门 回文自动机的好题啊 先建一个回文自动机,然后记$dp[i]$表示转移到$i$节点代表的回文串的最少的需要次数 首先肯定2操作越多越好,经过2操作之后的串必定是一个回文串,所以最后的答案肯定是由 ...
随机推荐
- swoole中websoket创建在线聊天室(php)
swoole中websoket创建在线聊天室(php) swoole现仅支持Linix,macos 创建websocket服务器 首先现在服务器创建一个websocket服务器 <?php // ...
- ssh连接不上vmware虚拟机centos7.5
在vmware中安装centos7.5后,手动设置IP地址192.168.1.5,发现主机ping不通虚拟机的IP,以下是我的解决办法 1.vmware设置选择仅主机模式 2.在主机查看vmnet1( ...
- python学习笔记 | PyCharm创建文件时自动添加头文件
File Settings Editor File and Code Templates Python Script 然后在右边的框中写入信息就可以啦: # -*- coding: utf-8 -*- ...
- Java基础学习总结笔记
Java基础 Java常用内存区域 栈内存空间:存储引用堆内存空间的地址 堆内存空间:保存每个对象的具体属性内容 全局数据区:保存static类型的属性 全局代码区:保存所有的方法定义 修饰符 权限修 ...
- CPNDet:粗暴地给CenterNet加入two-stage精调,更快更强 | ECCV 2020
本文为CenterNet作者发表的,论文提出anchor-free/two-stage目标检测算法CPN,使用关键点提取候选框再使用两阶段分类器进行预测.论文整体思路很简单,但CPN的准确率和推理速度 ...
- zabbix 监控的数据
/usr/local/zabbix/bin/zabbix_sender --zabbix-server 192.168.1.10 --port 10051 --input-file /var/log/ ...
- 【Docker】runtime create failed: container_linux.go:345: 解决
------------------------------------------------------------------------------------------------- | ...
- 【Oracle】delete表后commit后怎么找回,方法
有些时候,不小心删除了一些需要的表,而且数据库不能停止,只能一直运行下去,这样的话很麻烦 下面介绍的方法就是删除表后通过时间戳后者scn找回删除的数据 模拟实验环境: 创建一个新表 SQL> c ...
- P2327 [SCOI2005]扫雷(递推)
题目链接: https://www.luogu.org/problemnew/show/P2327 题目描述 相信大家都玩过扫雷的游戏.那是在一个$n*m$的矩阵里面有一些雷,要你根据一些信息找出雷来 ...
- iptables原理及防火墙规则语法基础
Iptables 防火墙 学习总结: 三张表介绍: filter负责过滤数据包,包括的规则链有,input(进),output(出)和forward(转发); nat则涉及到网络地址转换,包括的规则 ...