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

you need to nd out how to synthesize such good viruses.

We have prepared for you a set of strings of the letters A, G, T and C. They correspond to the

DNA nucleotide sequences of viruses that we want to synthesize, using the following operations:

• Adding a nucleotide either to the beginning or the end of the existing sequence.

• Replicating the sequence, reversing the copied piece, and gluing it either to the beginning or to

the end of the original (so that e.g., AGTC can become AGTCCTGA or CTGAAGTC).

We're concerned about efficiency, since we have very many such sequences, some of them very long.

Find a way to synthesize them in a minimum number of operations.

Input

The rst line of input contains the number of test cases T. The descriptions of the test cases follow:

Each test case consists of a single line containing a non-empty string. The string uses only the

capital letters `A', `C', `G' and `T' and is not longer than 100 000 characters.

Output

For each test case, output a single line containing the minimum total number of operations necessary

to construct the given sequence.

Sample Input

4

AAAA

AGCTTGCA

AAGGGGAAGGGGAA

AAACAGTCCTGACAAAAAAAAAAAAC

Sample Output

3

8

6

18

参考大牛的博客

http://www.cnblogs.com/clrs97/p/4700658.html

#include <iostream>
#include <string.h>
#include <algorithm>
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include <map> using namespace std;
typedef long long int LL;
const int maxn=1e5+5;
map<char,int> m;
int n;
char str[maxn];
int f[maxn];
struct Tree
{
int next[maxn][4];
int fail[maxn];
int train[maxn];
int len[maxn];
int num[maxn];
int cnt[maxn];
int s[maxn];
int last;
int p;
int n;
int new_node(int x)
{
memset(next[p],0,sizeof(next[p]));
len[p]=x;
return p++;
}
void init()
{
p=0;
new_node(0);
new_node(-1);
last=0;n=0;
s[0]=-1;
fail[0]=1;
}
int get_fail(int x)
{
while(s[n-len[x]-1]!=s[n])
x=fail[x];
return x;
}
int get_fail2(int x,int pos)
{
while(s[n-len[x]-1]!=s[n]||(len[x]+2)*2>len[pos])
x=fail[x];
return x;
}
void add(char xx)
{
int x=m[xx];
s[++n]=x;
int cur=get_fail(last);
if(!(last=next[cur][x]))
{
int now=new_node(len[cur]+2);
fail[now]=next[get_fail(fail[cur])][x];
if(len[now]<=2)
train[now]=fail[now];
else
train[now]=next[get_fail2(train[cur],now)][x]; next[cur][x]=now;
last=now;
}
}
}tree;
int ans;
int q[maxn];
int rear,head;
int main()
{
int t;
scanf("%d",&t);
m['A']=0;m['C']=1;m['G']=2;m['T']=3;
while(t--)
{
scanf("%s",str);
int len=strlen(str);
tree.init();
ans=len;
for(int i=0;i<len;i++)
{
tree.add(str[i]);
}
memset(f,0,sizeof(f));
for(int i=2;i<tree.p;i++)
{
if(tree.len[i]&1)
f[i]=tree.len[i];
}
f[0]=1;
q[0]=0;
head=0;rear=1;
int x,y;
while(head<rear)
{
x=q[head++];
for(int i=0;i<4;i++)
{
if(tree.next[x][i])
{
y=tree.next[x][i];
f[y]=f[x]+1;
f[y]=min(f[y],tree.len[y]/2-tree.len[tree.train[y]]+f[tree.train[y]]+1);
ans=min(ans,len-tree.len[y]+f[y]);
q[rear++]=y;
} }
}
printf("%d\n",ans);
}
return 0;
}

UVALive 6933 Virus synthesis(回文树)的更多相关文章

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

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

  2. BZOJ 4044 Virus synthesis (回文自动机+dp)

    题目大意: 你可以在一个串的开头或者末尾加入一个字符,或者把当前整个串$reverse$,然后接在前面或者后面,求达到目标串需要的最少操作次数 对目标串建出$PAM$ 定义$dp[x]$表示当前在回文 ...

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

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

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

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

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

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

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

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

  7. luogu P4762 [CERC2014]Virus synthesis (回文自动机)

    大意: 初始有一个空串, 操作(1)在开头或末尾添加一个字符. 操作(2)在开头或末尾添加该串的逆串. 求得到串$S$所需最少操作数. 显然最后一定是由某个偶回文通过添加字符得到的, 那么只需要求出所 ...

  8. 回文树(回文自动机PAM)小结

    回文树学习博客:lwfcgz    poursoul 边写边更新,大概会把回文树总结在一个博客里吧... 回文树的功能 假设我们有一个串S,S下标从0开始,则回文树能做到如下几点: 1.求串S前缀0~ ...

  9. HDU3948 & 回文树模板

    Description: 求本质不同回文子串的个数 Solution: 回文树模板,学一学贴一贴啊... Code: /*================================= # Cre ...

随机推荐

  1. C复杂声明举例

    首先,一些国外的研究成果: 一个用英语解析复杂声明的网站:http://cdecl.org 图表说明复杂声明(英):http://c-faq.com/decl/spiral.anderson.html ...

  2. python学习之winreg模块

    winreg模块将Windows注册表API暴露给了python. 常见方法和属性 winreg.OpenKey(key,sub_key,reserved = ,access = KEY_READ) ...

  3. 模拟元素的title属性,自定义Vue指令

    function showTitle(el, title) { const popover = getPopover() const popoverStyle = popover.style if ( ...

  4. MultipartEntity 乱码

    MultipartEntity multipartEntity = new MultipartEntity(HttpMultipartMode.BROWSER_COMPATIBLE, null, Ch ...

  5. poj2774(后缀数组水题)

    http://poj.org/problem?id=2774 题意:给你两串字符,要你找出在这两串字符中都出现过的最长子串......... 思路:先用个分隔符将两个字符串连接起来,再用后缀数组求出h ...

  6. 本系列love2d示例代码错误集中整理

    3.输入和音乐 音乐不是循环播放的,可以在love.audio.play(music) 之前添加music:setLooping(true)

  7. Unix domain socket IPC

    UNIX Domain socket 虽然网络socket也可用于同一台主机的进程间通讯(通过lo地址127.0.0.1),但是unix domain socket用于IPC更有效率:不需要经过网络协 ...

  8. iBATIS SQL Maps

    让我们重回到车辆管理系统和张三的故事中. 在 iBATIS SQL Maps 的世界里也存在 one-to-many.many-to-one 的关系,想必你已经对这些概念驾轻就熟了.好!还是每个 Pe ...

  9. 【BZOJ】1093: [ZJOI2007]最大半连通子图(tarjan+拓扑序)

    http://www.lydsy.com/JudgeOnline/problem.php?id=1093 两个条件综合起来加上求最大的节点数,那么很明显如果是环一定要缩点. 然后再仔细思考下就是求da ...

  10. openssl升级并发症

    简单介绍一下系统环境: 操作系统:redhat6.3 ,安装的主要涉及到的包有: root@192.168.100.252:/root# rpm -qa | grep ssh openssh-.3p1 ...