[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. PHP 自定义 alert 跳转方法

    /** * 跳转方法 * @param $msg * @param null $path * @param null $parent */ public function alert($msg,$pa ...

  2. 搭乘“AI大数据”快车,肌肤管家,助力美业数字化发展

    经过疫情的发酵,加速推动各行各业进入数据时代的步伐.美业,一个通过自身技术.产品让用户变美的行业,在AI大数据的加持下表现尤为突出. 对于美妆护肤企业来说,一边是进入存量市场,一边是疫后的复苏期,一边 ...

  3. pidof

    pidof 服务名称,就可以查看到服务占用的进程号

  4. SAPCAR使用说明

    1.首先看一下SAPCAR的功能usage:create a new archive:SAPCAR -c[vir][f archive] [-P] [-C directory]   [-A filen ...

  5. EntityFramework Core如何映射动态模型?

    前言 本文我们来探讨下映射动态模型的几种方式,相信一部分童鞋项目有这样的需求,比如每天/每小时等生成一张表,此种动态模型映射非常常见,经我摸索,这里给出每一步详细思路,希望能帮助到没有任何头绪的童鞋, ...

  6. JS实现植物大战僵尸小游戏,代码记录及效果展示

    前几天看到了一个很有趣的demo,用js制作植物大战僵尸小游戏,本着学习的心态,对照着做了一下,发现这里面的一些代码设计的确很精妙,这里分享下源码和效果,如果有需要,可以看下. 效果如下: 下载地址

  7. HTML部分

    1.说一下<label>标签的用法 label标签主要是方便鼠标点击使用,扩大可点击的范围,增强用户操作体验 2.说一下事件代理? 事件委托是指将事件绑定到目标元素的父元素上,利用冒泡机制 ...

  8. SpringCloud zuul 网关限流分析

    最近项目中 spring cloud zuul 运用到限流功能,打算配置一下就直接使用,不过在压测与调优过程中遇到一些没有预测到的问题,附上排查与解析结果 yml.pom配置 强烈推荐,按最新gith ...

  9. 电脑微信电脑PC 多开/防撤回 补丁

    简介 经常使用微信电脑版的用户都会发现一个蛋疼的事情,那就是微信PC版不支持多开,也就是不能同时登陆多个账号,这对于需要在电脑上登陆多个微信账号的朋友来说肯定是极其的不方便.另外有的时候别人撤回了一些 ...

  10. Java层面上下文切换

    前言 在过去单CPU时代,单任务在一个时间点只能执行单一程序.之后发展到多任务阶段,计算机能在同一时间点并行执行多任务或多进程.虽然并不是真正意义上的"同一时间点",而是 多个任务 ...