原文链接https://www.cnblogs.com/zhouzhendong/p/CF-100543G.html

题目传送门 - CF-Gym100543G

题意

  你可以对一个字符串进行以下两种操作:

  1.  在其头或者尾部加入一个新字符

  2.  翻转当前字符串,并把他拼接在当前字符串的前面或者后面

  给你 T 组询问,每组询问一个字符串,问你至少要多少次操作才能生成这个串。

  字符集 = ${'A','C','G','T'}$ ,字符串串长 $\leq 100000$

题解

  第一次写回文自动机。现学现用。

  写完调不出样例。网上看了看 Claris 的代码。研究了一下,继续调。样例是过了,一交 wa 。思索之后,重新打开 Claris 的博客。然后把代码改的和他差不多了 QAQ

  做法:

  我们先建一棵 PAM 。

  然后考虑在 PAM 上面 DP 。

  令当前串在 PAM 上面的状态为 $x$ 。

  考虑长度为 偶数 的回文串,分两种情况:

    折半,令节点 $y$ 为长度小于等于 $len_x$ 的一般的最长回文子串,则 $ dp_x=\min(dp_x,dp_y+(\cfrac {len_x}{2} - len_y) + 1) $

    删除两侧字符,令节点 $y$ 为当前回文串删除两侧节点得到,那么由于我们可以先折半再删除,所以 $dp_x=min(dp_x,dp_y+1)$ 。

  考虑长度为 奇数 的回文串,令 $dp_i=len_i$,分两种情况说明他是对的:

    该串下一步暴力填充至完成全串: 则选择该串不如直接选择偶串,故令 $dp_i=len_i$ 不亏。

    该串由偶串折半而来,那么由于在折半前有偶串的“删除两侧字符”这个转移,故不需要在奇串的转移中加入删除左侧或者右侧字符的转移 。

  具体做法见代码。

代码

#include <bits/stdc++.h>
using namespace std;
const int N=100005;
struct PAM{
static const int C=4;
int Next[N][C],fail[N],len[N],s[N],last,n,p;
int Half[N];
int newnode(int L){
memset(Next[p],0,sizeof Next[p]);
len[p]=L;
return p++;
}
void init(){
p=last=n=Half[0]=Half[1]=0;
newnode(0),newnode(-1);
s[0]=-1,fail[0]=1,fail[1]=0;
}
int getfail(int x){
while (s[n-len[x]-1]!=s[n])
x=fail[x];
return x;
}
void add(int c){
s[++n]=c;
int x=getfail(last);
if (!Next[x][c]){
int y=newnode(len[x]+2);
fail[y]=Next[getfail(fail[x])][c];
if (len[y]<=2)
Half[y]=fail[y];
else {
int z=Half[x];
while (s[n-len[z]-1]!=s[n]||(len[z]+2)*2>len[y])
z=fail[z];
Half[y]=Next[z][c];
}
Next[x][c]=y;
}
last=Next[x][c];
}
}pam;
int T,n,Turn[300],dp[N];
int q[N],head,tail;
char s[N];
int main(){
Turn['A']=0,Turn['C']=1,Turn['G']=2,Turn['T']=3;
scanf("%d",&T);
while (T--){
scanf("%s",s);
n=strlen(s);
pam.init();
for (int i=0;i<n;i++)
pam.add(Turn[s[i]]);
// 考虑长度为 偶数 的串,分两种情况:
// 折半
// 删除两侧字符
// 考虑长度为 奇数 的串,分两种情况:
// 该串下一步暴力填充至完成全串: 则选择该串不如直接选择偶串,故令 dp[i]=len[i]
// 该串由偶串折半而来,那么由于在折半前有偶串的“删除两侧字符”这个转移,故不需要在奇串的转移中加入删除左侧或者右侧字符的转移
for (int i=2;i<pam.p;i++)
if (pam.len[i]&1)
dp[i]=pam.len[i];
int ans=n;
head=tail=0,dp[0]=1,q[++tail]=0;
while (head<tail)
for (int x=q[++head],i=0;i<4;i++){
int y=pam.Next[x][i];
if (!y)
continue;
dp[y]=min(dp[x]+1,pam.len[y]/2-pam.len[pam.Half[y]]+dp[pam.Half[y]]+1);
ans=min(ans,n-pam.len[y]+dp[y]);
q[++tail]=y;
}
printf("%d\n",ans);
}
return 0;
}

  

Codeforces Gym100543G Virus synthesis 字符串 回文自动机 动态规划的更多相关文章

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

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

  2. 洛谷P4762 [CERC2014]Virus synthesis(回文自动机+dp)

    传送门 回文自动机的好题啊 先建一个回文自动机,然后记$dp[i]$表示转移到$i$节点代表的回文串的最少的需要次数 首先肯定2操作越多越好,经过2操作之后的串必定是一个回文串,所以最后的答案肯定是由 ...

  3. bzoj 4044: [Cerc2014] Virus synthesis【回文自动机+dp】

    建回文自动机,注意到一个回文串是可以通过一个长度小于等于这个串长度的一半的回文串添上一些字符然后复制得到的,也就是在自动机上向fa走,相当于treedp 每次都走显然会T,记录一个up,指向祖先中最下 ...

  4. bzoj 4044 Virus synthesis - 回文自动机 - 动态规划

    题目传送门 需要高级权限的传送门 题目大意 要求用两种操作拼出一个长度为$n$的只包含'A','T','G','C'的字符串 在当前字符串头或字符串结尾添加一个字符 将当前字符串复制,将复制的串翻转, ...

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

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

  6. UVALive 6933 Virus synthesis(回文树)

    Viruses are usually bad for your health. How about ghting them with... other viruses? In this proble ...

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

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

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

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

  9. bzoj 4044: Virus synthesis 回文自动机

    题目大意: 你要用ATGC四个字母用两种操作拼出给定的串: 将其中一个字符放在已有串开头或者结尾 将已有串复制,然后reverse,再接在已有串的头部或者尾部 一开始已有串为空.求最少操作次数. le ...

随机推荐

  1. Python-Django-Ajax进阶

    ajax上传文件: <h2>基于ajax上传文件</h2><p>名字 <input type="text" id="filena ...

  2. PYTHON- 操作系统和python程序

    操作系统基础 应用程序的启动:(重点!!!) python解释器安装,多版本共存 执行python程序的两种方式 运行一个python程序经历的三个阶段(重要) python 的内存管理 ====== ...

  3. swift 学习- 11 -- 属性

    // '属性'将值跟特定的类, 结构体或枚举关联, 存储属性常量或变量作为实例的一部分,而计算属性计算(不是存储) 一个值, 计算属性可以用于 类, 结构体, 枚举, 存储属性只能用于 类 和 结构体 ...

  4. SQL Server 2016 Failover Cluster + ALwaysOn

    SQL Server 2016 Failover Cluster + ALwaysOn 环境的搭建 近期公司为了提高服务的可用性,就想到了部署AlwaysOn,之前的环境只是部署了SQL Server ...

  5. 疯狂Workflow讲义——基于Activiti的工作流应用开 PDF 下载

    <疯狂Workflow讲义--基于Activiti的工作流应用开> 一:文档获取下载方式: 1:花20CSDN积分:可以下载:http://download.csdn.net/downlo ...

  6. Confluence 6 中样式化字体

    Confluence 提供了通过层叠样式表(CSS)调整页面展示情况的能力.本页面帮助你理解如何在 Confluence 中使用一些 CSS 样式修改字体样式和字体大小. 下面的代码为自定义的字体代码 ...

  7. Java的家庭记账本程序(C)

    日期:2019.2.4 博客期:029 星期一 今天初步修改了程序,实现了几个基本的功能: 个人信息管理.除查询以外的全部功能!

  8. 用flask实现的分页

    一.flask实现的分页组件 from urllib.parse import urlencode,quote,unquote class Pagination(object): "&quo ...

  9. 高斯消元-poj1222熄灯问题状态压缩解法

    有点自闭的..为什么我最后的答案是倒着来的啊.. 搞明白了:因为一开始构造的系数就是反着的,,所以主元也倒过来了.. #include<iostream> #include<cstd ...

  10. vue和stylus在subline中显示高亮

    首先: 安装这两个插件   Vue Syntax Highlight    和    stylus 1.按住 ctrl + shift + p 2.输入:install Package 3.输入: V ...