[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. swoole中websoket创建在线聊天室(php)

    swoole中websoket创建在线聊天室(php) swoole现仅支持Linix,macos 创建websocket服务器 首先现在服务器创建一个websocket服务器 <?php // ...

  2. [日常填坑系列]CAP食用指南-版本引用问题

    一.前言 最近,由于好久没升级底层框架,一直用着netcore2.2版本,导致有些包没能更新到最新的版本,例如:CAP. 然而,在最近升级到CAP:3.1.2版本的时候,发现有点小坑,只能退回到CAP ...

  3. .netcore 急速接入第三方登录,不看后悔

    新年新气象,趁着新年的喜庆,肝了十来天,终于发了第一版,希望大家喜欢. 如果有不喜欢看文字的童鞋,可以直接看下面的地址体验一下: https://oauthlogin.net/ 前言 此次带来得这个小 ...

  4. Nginx Consul nginx-upsync-module

    nginx consul nginx-upsync-module 依赖包: yum -y install libpcre3 libpcre3-dev ruby zlib1g-dev patch 下载n ...

  5. 【ASM】介绍Oracle自带的一些ASM维护工具 (kfod/kfed/amdu)

    转自:http://blog.csdn.net/wenzhongyan/article/details/47043253 非常感谢作者的文章,很有价值!至此转载,非常感谢 1.前言 ASM(Autom ...

  6. leetcode 1240. 铺瓷砖(回溯,DFS)

    题目链接 https://leetcode-cn.com/problems/tiling-a-rectangle-with-the-fewest-squares/ 题意: 用尽可能少的正方形瓷砖来铺地 ...

  7. ctfhub技能树—文件上传—文件头检查

    打开靶机 尝试上传一个php文件 抓包修改 放包 制作图片马 上传图片马,并修改文件类型为png 测试连接 查找flag 成功拿到flag

  8. 实现所有SAP设备打印机并行打印

    SAP版本:ECC 6.0 701 1.如何实现所有SAP设备打印机并行打印? I.通过事务码:SPAD,进入假脱机管理初始屏幕.点击左上角的菜单中 配置(c)=>输出设备,进入SAP系统 输出 ...

  9. 与数论的厮守05:gcd(a,b)=gcd(b,a mod b)的证明

    \[设c=gcd(a,b),那么a可以表示为mc,b可以表示为nc的形式.然后令a=kb+r,那么我们就\\ 只需要证明gcd(b,r)=c即可.{\because}r=a-kb=mc-knc,{\t ...

  10. HA工作机制及namenode向QJM写数据流程

    HA工作机制 (配置HA高可用传送门:https://www.cnblogs.com/zhqin/p/11904317.html) HA:高可用(7*24小时不中断服务) 主要的HA是针对集群的mas ...