原文链接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. Windows平台下,Java性能分析工具VisualVM的Tomcat8的配置

    VisualVM在JDK6版本及以上已经自带这个应用. 位置:C:\Program Files (x86)\Java\jdk1.8.0_60\bin\jvisualvm.exe   在Windows环 ...

  2. elasticsearch中的java.io.IOException: 远程主机强迫关闭了一个现有的连接

    [2018-07-31T14:29:41,289][WARN ][o.e.x.s.t.n.SecurityNetty4HttpServerTransport] [9rTGh-y] caught exc ...

  3. AES加解密程序的实现

    AES加解密程序的实现正常情况,用户不能访问sys.dbms_crypto,需要DBA授权:grant execute on dbms_crypto to crm;建立加解密的PKG_AES包:CRE ...

  4. 弃 Java 而使用 Kotlin 的你后悔了吗?| kotlin将会是最好的开发语言

    自从 2011 年发布以来,Kotlin 凭借强大的功能在开发者中的欢迎程度与日俱增.且在一年前,Google 宣布 Kotlin 正式成为 Android 官方开发语言,由此引发了从 Java 迁移 ...

  5. Confluence 6 配置校验和识别

    校验你的设置 查看你 Confluence 当前使用的设置,请参考 Viewing System Properties 页面中的内容. 识别系统属性 请参考 Recognized System Pro ...

  6. js数组的实例方法sort() 排序方法的运用,不再只是.sort()

    1, sort() 不传回调函数的话,默认按照字母顺序(字符编码)的顺序进行排序. 2, sort() 通过传回调函数来控制从小到大的排序还是从大到小的排序: var arr = [1,23,5,6, ...

  7. 开源框架 ImageLoader +ListView+GridView+RecyclerView 浅解

    下载地址 链接:https://pan.baidu.com/s/1ebz99pcuvHg2bODgeOtSbg 提取码:ia39 一.导入jar包或者添加依赖 jar包地址 导入jar包:将下载的ja ...

  8. 用flask的扩展实现的简单的页面登录

    from flask import Flask,render_template,request,redirect,session app = Flask(__name__,template_folde ...

  9. python(5):scipy之numpy介绍

    python 的scipy 下面的三大库: numpy, matplotlib, pandas scipy 下面还有linalg 等 scipy 中的数据结构主要有三种: ndarray(n维数组), ...

  10. node.js 框架express有关于router的运用

    1.express 路由入门 const express = require('express'); let server = express(); server.listen(8087); //用户 ...