题意

你要用 \(ATGC\) 四个字母用两种操作拼出给定的串:

  1. 将其中一个字符放在已有串开头或者结尾
  2. 将已有串复制,然后 \(reverse\) ,再接在已有串的头部或者尾部

一开始已有串为空。求最少操作次数。

\(len\le100000\)

Sol

首先有个结论

每次形成偶数长度回文串的最后一步一定是操作 \(2\)

那么考虑一个 \(DP\)

设 \(f[i]\) 表示形成 \(i\) 表示的字符串需要的最少步数

可以去掉首和尾转移来,可以由它的一个前缀或者后缀转移来

如果是个偶数长度的字符串

可以由某个长度小于等于它一半的字符串增长到它的长度后翻倍而来

可以由它去掉首尾的串一步转移而来,因为去掉首位仍然是偶数长度而且形成偶数长度回文串的最后一步一定是操作 \(2\)

那么直接用回文树实现

求某个长度小于等于它一半的字符串直接建树的时候暴力跳一下(雾

# include <bits/stdc++.h>
# define IL inline
# define RG register
# define Fill(a, b) memset(a, b, sizeof(a))
using namespace std;
typedef long long ll; IL int Input(){
RG int x = 0, z = 1; RG char c = getchar();
for(; c < '0' || c > '9'; c = getchar()) z = c == '-' ? -1 : 1;
for(; c >= '0' && c <= '9'; c = getchar()) x = (x << 1) + (x << 3) + (c ^ 48);
return x * z;
} const int maxn(1e5 + 5); int f[maxn], son[4][maxn], trans[666], half[maxn], len[maxn], fa[maxn], num[maxn], tot, last, pre[maxn];
char s[maxn]; IL void Init(){
for(RG int i = 0; i <= tot; ++i){
len[i] = fa[i] = half[i] = 0;
for(RG int j = 0; j < 4; ++j) son[j][i] = 0;
}
fa[0] = fa[1] = 1, len[1] = -1, tot = 1, last = 0;
} IL void Extend(RG int pos, RG int c){
RG int p = last;
while(s[pos - len[p] - 1] != s[pos]) p = fa[p];
if(!son[c][p]){
RG int np = ++tot, q = fa[p];
while(s[pos - len[q] - 1] != s[pos]) q = fa[q];
len[np] = len[p] + 2, fa[np] = son[c][q];
son[c][p] = np, pre[np] = p;
if(s[pos - len[half[p]] - 1] == s[pos]) half[np] = son[c][half[p]];
else half[np] = fa[np];
while((len[half[np]] << 1) > len[np]) half[np] = fa[half[np]];
}
last = son[c][p];
} int main(){
trans['C'] = 1, trans['G'] = 2, trans['T'] = 3;
for(RG int t = Input(), n = 0; t; --t){
Init(), scanf(" %s", s + 1), n = strlen(s + 1);
for(RG int i = 1; i <= n; ++i) Extend(i, trans[s[i]]);
RG int ans = n;
for(RG int i = 2; i <= tot; ++i){
f[i] = min(len[i], f[fa[i]] + len[i] - len[fa[i]]);
if(len[i] & 1) f[i] = min(f[pre[i]] + 2, f[i]);
else{
f[i] = min(f[i], pre[i] ? f[pre[i]] + 1 : 2);
f[i] = min(f[i], f[half[i]] + (len[i] >> 1) - len[half[i]] + 1);
}
ans = min(ans, f[i] + n - len[i]);
}
printf("%d\n", ans);
}
return 0;
}

Bzoj4044 Virus synthesis的更多相关文章

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

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

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

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

  3. luogu_4762: [CERC2014]Virus synthesis

    洛谷_4762:[CERC2014]Virus synthesis 题目描述: 初始有一个空串,利用下面的操作构造给定串\(S\).\(len(S)\leq10^5\) 1: 串开头或末尾加一个字符. ...

  4. LG4762 Virus synthesis

    Virus synthesis 初始有一个空串,利用下面的操作构造给定串 S . 串开头或末尾加一个字符 串开头或末尾加一个该串的逆串 求最小化操作数, ∣S∣≤105 . 题解 显然应该多使用操作2 ...

  5. [CERC2014]Virus synthesis【回文自动机+DP】

    [CERC2014]Virus synthesis 初始有一个空串,利用下面的操作构造给定串 SS . 1.串开头或末尾加一个字符 2.串开头或末尾加一个该串的逆串 求最小化操作数, \(|S| \l ...

  6. bzoj4044 [Cerc2014] Virus synthesis

    回文自动机上dp f[x]表示形成x代表的回文串所需的最小步数, 若len[x]为奇数,f[x]=len[x],因为即使有更优的,也是直接添加,没有复制操作,那样就不用从x转移了. 若len[x]为偶 ...

  7. BZOJ4044: [Cerc2014] Virus synthesis(回文树+DP)

    Description Viruses are usually bad for your health. How about fighting them with... other viruses? ...

  8. [CERC2014] Virus synthesis

    设f[i]为形成极长回文串i的最小操作数.答案为min f[i]+n-len[i]. 在不形成偶回文的情况下形成奇回文的最小操作数为该串长度.可以不考虑(但ans赋为len). 正确性基于: 1)奇. ...

  9. Codeforces Gym100543G Virus synthesis 字符串 回文自动机 动态规划

    原文链接https://www.cnblogs.com/zhouzhendong/p/CF-100543G.html 题目传送门 - CF-Gym100543G 题意 你可以对一个字符串进行以下两种操 ...

随机推荐

  1. google Agent

    一句话:改HOSTS文件 有时候要查看appengine.google.com的后台,但死活上不去,怎么办?还是那个老办法: 1.在cmd下Ping www.google.com.hk,获得IP地址, ...

  2. docker安装Tomcat软件,部署项目

    1 搜索tomcat镜像 $ sudo docker search tomcat NAME DESCRIPTION STARS OFFICIAL AUTOMATED tomcat Apache Tom ...

  3. C#接口实现多态

    我比较喜欢对感兴趣的理论进行反复的理解甚至理解背诵下来,接下来再复习一下什么叫多态(哈哈哈) 多态:在同一粒度视图下对相同类型的事物不做区别的统一操作 接下来看一下接口和引擎类是如何实现多态的: 一. ...

  4. angluarjs的tab标签

    JS代码 $scope.tabs = []; $rootScope.data = { current: "3" // 1代表张三,2代表李四,3代表王五 }; $rootScope ...

  5. JavaScript设计模式(三) - 策略模式

    什么是策略模式? 策略模式支持在运行时由使用者选择合适的算法,对于使用者而言不用关心背后的具体实现,由使用者自动根据当前程序执行的上下文和配置,从已有的算法列列表中选择出合适的算法来处理当前任务.   ...

  6. C#多线程学习一

    一.概述:C#支持多线程并行执行程序,一个线程有他单独的执行路径,能够与其他线程同时执行,一个程序是由一个单线程开始,该单线程由CLR(公共语言运行时)和操作系统创建而成,并具有多线程创建额外线程的功 ...

  7. django notes 五:Writing models

    models 其实也没什么好说的,就是普通的 python 类 settings 中配置数据库连接 DATABASES = { 'default': { 'ENGINE': 'django.db.ba ...

  8. ActiveMQ安装及使用

    1 安装环境 1.需要jdk2.安装Linux系统.生产环境都是Linux系统. 2 安装步骤 第一步: 把ActiveMQ 的压缩包上传到Linux系统.第二步:解压缩. 第三步:关闭防火墙 临时关 ...

  9. maven多模块下新建子模块

    选中parent模块,右键选择new---others 选择Maven---Maven Module,点击下一步 填写Module Name,其他默认,点击下一步 默认,下一步 默认,点击完成

  10. 【扫盲】】32位和64位Windows的区别

    用户购买windows安装盘或者重新安装操作系统的时候,通常会遇到这个问题,就是不知道该如何选择使用32位操作系统和64位操作系统,有人说64位系统速度快,其实理论上确实是这样,不过具体还要根据你的个 ...