洛谷_4762:[CERC2014]Virus synthesis

题目描述:

  • 初始有一个空串,利用下面的操作构造给定串\(S\)。\(len(S)\leq10^5\)

    • 1: 串开头或末尾加一个字符。
    • 2: 串开头或末尾添加一个该串的逆串。

输入描述:

  • 给出一个\(T\)表示要处理的字符串的数量。
  • 接下来第\(2\)~\(T+1\)行每行给出一个字符串。

输出描述:

  • 对于每一个字符串,输出一个正整数表示答案。

思路:

  • 回文自动机。
  • 先建立一个回文自动机,然后记\(f(i)\)表示转移到\(i\)节点结尾代表的回文串的最少需要的次数。
  • 操作\(2\)肯定越多越好,经过操作\(2\)得到的肯定是一个回文串,那么最后的答案肯定是回文串\(+\)暴力
    • 可以知道最后答案为\(ans=min(ans,f(i)+strlen-len(i))\)
  • 对于一个串\(i\),如果在他前面和后面加上一个相同的字母可以形成回文串\(j\),则\(f(j)=f(i)+1\)。
  • 为什么是对的呢?就相当于形成\(i\)只有回文串的前一半,先在前一半的前面加上那个字母后再进行操作\(2\)就可以变成字符串\(j\)了。
  • 对应在自动机里就是如果一个节点有子节点,那么\(f(son)=f(fa)+1\)。
  • 对于遍历到的位置\(x\),他的\(trans\)指针指向\(y\),那么有\(f(x)=min(f(x),f(y)+\:(len(x)/2-len(y))\:+1)\)
  • 最后对\(trie\)图进行\(bfs\)更新答案。

代码:

#include<bits/stdc++.h>
using namespace std;
const int maxn = 1e5 +10, INF = 0x3f3f3f3f;
int T, ans; char s[maxn];
int cnt, trie[maxn][6], trans[maxn], w[110];
int len[maxn], fail[maxn], len_str, last; int f[maxn]; void init()
{
w['A'] = 0, w['T'] = 1, w['C'] = 2, w['G'] = 3;
scanf("%s", s + 1);
len_str = ans = strlen(s + 1);
cnt = 1, last = 0;
len[0] = 0, len[1] = -1;
fail[0] = 1, fail[1] = 0;
memset(trie[0], 0, sizeof(trie[0]));
memset(trie[1], 0, sizeof(trie[1]));
} inline int get_fail(int las, int i)
{
while(s[i - len[las] - 1] != s[i])
las = fail[las];
return las;
} void build_PAM()
{
for(int i = 1; i <= len_str; i++)
{
int num = w[int(s[i])];
int p = get_fail(last, i);
if(!trie[p][num])
{
len[++cnt] = len[p] + 2;
memset(trie[cnt], 0, sizeof(trie[cnt]));
fail[cnt] = trie[get_fail(fail[p], i)][num];
trie[p][num] = cnt; //--------求trans指针
if(len[cnt] <= 2) trans[cnt] = fail[cnt];
else
{
int tmp = trans[p];
while((s[i - len[tmp] - 1] != s[i]) || ( ((len[tmp] + 2) * 2) > len[cnt]))
tmp = fail[tmp];
trans[cnt] = trie[tmp][num];
}
//--------
}
last = trie[p][num];
}
} int main()
{
scanf("%d", &T);
while(T--)
{
init(); build_PAM();
for(int i = 2; i <= cnt; i++)
f[i] = len[i]; f[0] = 1;
queue<int> q; q.push(0);
while(q.size())
{
int t = q.front(); q.pop();
for(int i = 0, x, y; i <= 3; i++)
{
x = trie[t][i]; if(!x) continue;
f[x] = f[t] + 1; y = trans[x];
f[x] = min(f[x], f[y]+1+len[x]/2-len[y]);
ans = min(ans, f[x]+len_str-len[x]);
q.push(x);
}
}
printf("%d\n", ans);
}
return 0;
}
/*
4
AAAA
AGCTTGCA
AAGGGGAAGGGGAA
AAACAGTCCTGACAAAAAAAAAAAAC
*/

luogu_4762: [CERC2014]Virus synthesis的更多相关文章

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

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

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

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

  3. bzoj4044 [Cerc2014] Virus synthesis

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

  4. [CERC2014] Virus synthesis

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

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

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

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

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

  7. BZOJ 4044 Luogu P4762 [CERC2014]Virus Synthesis (回文自动机、DP)

    好难啊..根本不会做..基本上是抄Claris... 题目链接: (bzoj)https://www.lydsy.com/JudgeOnline/problem.php?id=4044 (luogu) ...

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

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

  9. P4762 [CERC2014]Virus synthesis

    题意 真是道回文自动机好题. 首先考虑答案必定是一个回文串+剩余部分的形式,因此可以建出回文自动机,之后考虑每个长度为偶数的回文串. 对于一个长度为偶数的回文串,设它在回文自动机上对应的节点为\(x\ ...

随机推荐

  1. Docker 制作定制asp.netcore 的容器

    上文Windows docker k8s asp.net core的k8swebap镜像只是一个asp.net core程序,在实际生产中我们希望容器中还有一些其他程序,比如ssh 和telegraf ...

  2. Java可视化计算器

    利用java中的AWT和SWING包来做可视化界面. 首先来简单了解一下这两个包: AWT和Swing都是Java中用来做可视化界面的.AWT(Abstract Window Toolkit):抽象窗 ...

  3. java基础 接口总结

    在java9+版本中,接口的内容可以有: 1.成员变量其实是常量,格式:[public] [static] [final] 数据类型 常量名称 = 数组值:注意: 常量必须进行赋值,而且一旦赋值不能变 ...

  4. 在Asp.Net Core MVC 3.0 视图运行时编译

    在正常情况下,视图在生成的时候就会变为 xxx.Views.dll,在开发的时候,这样很不方便,因为很多的时候,我们只是修改一个样式,调整一些JavaScript代码,这个时候要把项目调试暂停下来,生 ...

  5. 异常详细信息: System.Security.SecurityException: 未找到源,不过,未能搜索部分或所有事件日志。 若要创建源,您需要用于读取所有事件日志的权限以确保新的源名称是唯一的。 不可访问的日志: Security。

    “/”应用程序中的服务器错误. 安全性异常 说明: 应用程序尝试执行安全策略不允许的操作.要授予此应用程序所需的权限,请与系统管理员联系,或在配置文件中更改该应用程序的信任级别. 异常详细信息: Sy ...

  6. CodeForces 536D Tavas in Kansas

    洛谷题目页面传送门 & CodeForces题目页面传送门 A和B在一张无向连通图\(G=(V,E),|V|=n,|E|=m\)上玩一个游戏,节点\(i\)有一个权值\(v_i\).A.B分别 ...

  7. Django---CBV和FBV的使用,CBV的流程,给视图加装饰器,Request对象方法,属性和Response对象,form表单的上传

    Django---CBV和FBV的使用,CBV的流程,给视图加装饰器,Request请求对象方法,属性和Response响应对象,form表单的上传 一丶CBV和FBV       在Django中存 ...

  8. dubbo循序渐进 - 使用Docker安装Nexus

    docker search nexus docker pull docker.io/sonatype/nexus3 mkdir -p /usr/local/nexus3/nexus-data /usr ...

  9. 面试题:android的安全机制有哪些

    1 uid . gid . gids Android 的权限分离的基础是建立在 Linux 已有的 uid . gid . gids 基础上的 . UID: Android 在 安装一个应用程序,就会 ...

  10. byte[],File和InputStream的相互转换

    File.FileInputStream 转换为byte[] File file = new File("test.txt"); InputStream input = new F ...