[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操作之后的串必定是一个回文串,所以最后的答案肯定是由 ...
随机推荐
- CSS 奇技淫巧:动态高度过渡动画
这个问题源自于掘金上的一个留言,一个朋友问到,为什么我下面这段代码的高度过渡动画失效了? 伪代码大概是这样: { height: unset; transition: all 0.3s linear; ...
- Oracle控制文件多路复用以及Oracle备份重建控制文件
控制文件中记录了oracle数据库的物理结构,也就是记录了数据库数据文件和日志文件的位置,控制文件中还记录了多种SCN,用这些SCN来确定数据文件和日志文件是否是正确的.如果不正确那么数据库就需要恢复 ...
- Docker-ce运用一:创建虚拟机
1.从远程仓库查看所需镜像 [root@localhost docker]# docker search centos8 NAME DE ...
- 【Maven】Maven 高级应用
Maven 高级应用 Maven 基础 Maven 是一个项目管理工具,它有如下好处: 节省磁盘空间 可以一键构建 可以跨平台使用 依赖传递和管理,提高开发效率 一键构建:Maven 自身集成了 To ...
- LeetCode106 从中序和后序序列构造二叉树
题目描述: 根据一棵树的中序遍历与后序遍历构造二叉树. 注意:你可以假设树中没有重复的元素. 例如,给出 中序遍历 inorder = [9,3,15,20,7] 后序遍历 postorder = [ ...
- 二 prometheus 监控 Redis
Prometheus 监控Redis需要用到redis_exporter客户端, Prometheus -> redis_exporter这个模式, 类似监控Mysql 一个思路. 1 ) 设置 ...
- (十九)hashlib模块
hashlib模块用于加密相关的操作,3.x里代替了md5模块和sha模块,主要提供 SHA1, SHA224, SHA256, SHA384, SHA512 ,MD5 算法 注意:md5和sha25 ...
- LeetCode383. 赎金信
题目 给定一个赎金信 (ransom) 字符串和一个杂志(magazine)字符串,判断第一个字符串 ransom 能不能由第二个字符串 magazines 里面的字符构成.如果可以构成,返回 tru ...
- ctfhub技能树—RCE—命令注入
打开靶机 查看页面信息 输入127.0.0.1进行测试 构造payload 127.0.0.1&ls 查看文件内容信息 127.0.0.1 & cat 179852221619745. ...
- Ubuntu 能ping通DNS 地址 无法解析域名
ping通qq百度都行,唯独谷歌不行, 主机能够ping通google的dns服务器地址 8.8.8.8,却无法解析域名 $ ping www.google.co.uk ping: unknown ...