原文链接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. MVC异步方法

    在mvc的开发过程中,有时候我们会需要在action中调用异步方法,这个时候会需要做一些特殊处理.我们会使用到await和async.对应的controller也应该是async的. 在MVC4中直接 ...

  2. Apache 和 Tomcat联系和区别

    作者:郭无心链接:https://www.zhihu.com/question/37155807/answer/72706896来源:知乎著作权归作者所有.商业转载请联系作者获得授权,非商业转载请注明 ...

  3. swift 实践- 01 -- UItableView的简单使用

    import UIKit class ViewController: UIViewController ,UITableViewDelegate,UITableViewDataSource{ over ...

  4. Modbus库开发笔记之七:Modbus其他辅助功能开发

    前面开发了各种应用,但是却一直没有提到一个问题,你就是对具体的数据进行读写操作.对于Modbus来说标准的数据有4种:线圈数据(地址:0000x).输入状态量数据(地址:1000x).保持寄存器数据( ...

  5. XmlDocument.Load(url) 本地和http远程

    XmlDocument.Load(url) 的使用 远程: string path = @"http://localhost:8080/Source/XMLConfig.xml"; ...

  6. anaconda中的包如何传到pycharm中使用?

    在pycharm的setting中设置 在project interpreter 中的 existing environment 中选择 anaconda3安装目录下的的 python.exe 就可以 ...

  7. Python继承、方法重写

    继承 在编写类时,并不是每次都要从空白开始.当要编写的类和另一个已经存在的类之间存在一定的继承关系时,就可以通过继承来达到代码重用的目的,提高开发效率. class one(): "&quo ...

  8. vue项目使用阿里巴巴矢量图标库教程

    前言:element-ui自带的图标库还是不够全,还是需要需要引入第三方icon,自己在用的时候一直有些问题,参考了些教程,详细地记录补充下. 对于我们来说,首选的当然是阿里icon库 地址:http ...

  9. C++11新特性--decltype (转)

    返回值 decltype(表达式) [返回值的类型是表达式参数的类型] 这个可也用来决定表达式的类型,就像Bjarne暗示的一样,如果我们需要去初始化某种类型的变量,auto是最简单的选择,但是如果我 ...

  10. spring cloud Eureka常见问题总结

    Spring Cloud中,Eureka常见问题总结. 指定Eureka的Environment 1 eureka.environment: 指定环境 参考文档:https://github.com/ ...