题意

你要用 \(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. Oracle数据库PL/SQL那点事情---修改过电脑的用户名

    在安装Oracle数据库的PL/SQL工具时候,电脑名称是重装系统后自动生成的用户名名称,作为程序员,有很强的强迫症,就想利用自己的英文名称作为自己电脑的名称,所以就修改了电脑的名称:结果PL/SQL ...

  2. day 08 课后作业

    # -*- coding: utf-8 -*-# @Time : 2018/12/27 17:27# @Author : Endless-cloud# @Site : # @File : day 8课 ...

  3. 河内塔问题(C++版)

    上次,我们讲了汉诺塔,今天我们来讲一讲和汉诺塔类似的题目<河内塔问题> 题目描述 Description 一位法国数学家曾编写过一个印度的古老传说:在世界中心贝拿勒斯(在印度北部)的圣庙里 ...

  4. 六、python中context.get()方法

    例:context.get('variant',False) 意思是如果context中不包括variant 就返回False.

  5. vue中的双向数据绑定详解

    前言 什么是数据双向绑定? vue是一个mvvm框架,即数据双向绑定,即当数据发生变化的时候,视图也就发生变化,当视图发生变化的时候,数据也会跟着同步变化.这也算是vue的精髓之处了.值得注意的是,我 ...

  6. com.alibaba.dubbo.rpc.RpcException: Failed to invoke remote method解决方法

    报错日记: Caused by: com.alibaba.dubbo.rpc.RpcException: Failed to invoke remote method: getUserAuthLeve ...

  7. js读取cookie信息

    1. 第一种方式读取cookie信息:用document.cookie.split(“; “)的方式把字符串分割成几个段,然后遍历整个数组 //javascript方法 function getCoo ...

  8. Java Struts(文件下载)

    1.从注册成功页面跳转至用户详情页面(跳转至UserListAction) 2.UserListAction调用service获得用户列表,并将这些数据传送到UserList.jsp中,UserLis ...

  9. win7下安装centos6.5后,开机无法进入选择双系统启动界面,只能启动centos的解决办法

    1.centos6.5下打开终端,进入/boot/grub ,vim grub.conf 将default=0 改为1,重启 2.重启后,又只能进入win7了.这个好解决.下载一个easyBCD,具体 ...

  10. 微软URLRewriter.dll的url重写的简单使用

    1.先下载MSDNURLRewriting.zip包,打开代码生成URLRewriter.dll文件: 2.将URLRewriter.dll文件引用到项目中: 3.在web.config文件中  &l ...