P4762 [CERC2014]Virus synthesis
题意
真是道回文自动机好题。
首先考虑答案必定是一个回文串+剩余部分的形式,因此可以建出回文自动机,之后考虑每个长度为偶数的回文串。
对于一个长度为偶数的回文串,设它在回文自动机上对应的节点为\(x\),我们对于每个\(x\)求出\(trans_x\)表示x的最长后缀回文串,满足\(len_{trans_x}\leqslant len_x/2\)。
之后设\(f_x\)表示\(x\)拼成\(x\)这个串的最小代价,我们从\(0\)(偶根)出发进行\(bfs\),中途计算\(f_x\)。
对于\(f_x\):
初值肯定是自身长度\(f_x=len_x\)。
如果存在一条边\((x,y)\),那么\(f_y=f_x+1\),因为我们可以在拼\(x\)时还没进行\(2\)操作时向\(x\)后面填一个字符,使其进行\(2\)操作后变为\(y\)。
同时\(f_x=min(f_x,f_{trans_x}+1+lem_x/2-len_{trans_x})\),即我们可以从\(trans_x\)变过来。
对于每个\(x\),它对答案的贡献是\(n-len_x+f_x\),\(n\)是字符串长度。
code:
#include<bits/stdc++.h>
using namespace std;
const int maxn=1e5+10;
const int inf=1e9;
int T,n,tot,last,ans;
int fail[maxn],len[maxn],trans[maxn],f[maxn];
int ch[maxn][5];
char s[maxn];
inline int change(char c)
{
if(c=='A')return 1;
if(c=='G')return 2;
if(c=='C')return 3;
if(c=='T')return 4;
return 2333;
}
inline void init()
{
for(int i=0;i<=tot;i++)
for(int j=1;j<=4;j++)
ch[i][j]=0;
fail[0]=1;len[1]=-1;
tot=1;last=0;
}
inline int getfail(int x,int pos)
{
while(s[pos-len[x]-1]!=s[pos])x=fail[x];
return x;
}
inline void add(int c,int pos)
{
int p=getfail(last,pos);
if(!ch[p][c])
{
int q=++tot,tmp;len[q]=len[p]+2;
tmp=getfail(fail[p],pos);
fail[q]=ch[tmp][c];ch[p][c]=q;
if(len[q]<=2)trans[q]=fail[q];
else
{
tmp=trans[p];
while(s[pos-len[tmp]-1]!=s[pos]||((len[tmp]+2)<<1)>len[q])tmp=fail[tmp];
trans[q]=ch[tmp][c];
}
}
last=ch[p][c];
}
inline void solve()
{
queue<int>q;
for(int i=2;i<=tot;i++)f[i]=len[i];
for(int i=1;i<=4;i++)if(ch[0][i])q.push(ch[0][i]);
while(!q.empty())
{
int x=q.front();q.pop();
f[x]=min(f[x],f[trans[x]]+1+len[x]/2-len[trans[x]]);
ans=min(ans,n-len[x]+f[x]);
for(int i=1;i<=4;i++)
{
if(!ch[x][i])continue;
int y=ch[x][i];
f[y]=min(f[y],f[x]+1);
q.push(y);
}
}
}
int main()
{
scanf("%d",&T);
while(T--)
{
scanf("%s",s+1);n=strlen(s+1);
s[0]='#';
init();
for(int i=1;i<=n;i++)add(change(s[i]),i);
ans=n;solve();
printf("%d\n",ans);
}
return 0;
}
P4762 [CERC2014]Virus synthesis的更多相关文章
- BZOJ 4044 Luogu P4762 [CERC2014]Virus Synthesis (回文自动机、DP)
好难啊..根本不会做..基本上是抄Claris... 题目链接: (bzoj)https://www.lydsy.com/JudgeOnline/problem.php?id=4044 (luogu) ...
- 洛谷P4762 [CERC2014]Virus synthesis(回文自动机+dp)
传送门 回文自动机的好题啊 先建一个回文自动机,然后记$dp[i]$表示转移到$i$节点代表的回文串的最少的需要次数 首先肯定2操作越多越好,经过2操作之后的串必定是一个回文串,所以最后的答案肯定是由 ...
- luogu P4762 [CERC2014]Virus synthesis (回文自动机)
大意: 初始有一个空串, 操作(1)在开头或末尾添加一个字符. 操作(2)在开头或末尾添加该串的逆串. 求得到串$S$所需最少操作数. 显然最后一定是由某个偶回文通过添加字符得到的, 那么只需要求出所 ...
- luogu_4762: [CERC2014]Virus synthesis
洛谷_4762:[CERC2014]Virus synthesis 题目描述: 初始有一个空串,利用下面的操作构造给定串\(S\).\(len(S)\leq10^5\) 1: 串开头或末尾加一个字符. ...
- [CERC2014]Virus synthesis【回文自动机+DP】
[CERC2014]Virus synthesis 初始有一个空串,利用下面的操作构造给定串 SS . 1.串开头或末尾加一个字符 2.串开头或末尾加一个该串的逆串 求最小化操作数, \(|S| \l ...
- bzoj4044/luoguP4762 [Cerc2014]Virus synthesis(回文自动机+dp)
bzoj4044/luoguP4762 [Cerc2014]Virus synthesis(回文自动机+dp) bzoj Luogu 你要用ATGC四个字母用两种操作拼出给定的串: 1.将其中一个字符 ...
- bzoj4044 [Cerc2014] Virus synthesis
回文自动机上dp f[x]表示形成x代表的回文串所需的最小步数, 若len[x]为奇数,f[x]=len[x],因为即使有更优的,也是直接添加,没有复制操作,那样就不用从x转移了. 若len[x]为偶 ...
- [CERC2014] Virus synthesis
设f[i]为形成极长回文串i的最小操作数.答案为min f[i]+n-len[i]. 在不形成偶回文的情况下形成奇回文的最小操作数为该串长度.可以不考虑(但ans赋为len). 正确性基于: 1)奇. ...
- bzoj 4044: [Cerc2014] Virus synthesis【回文自动机+dp】
建回文自动机,注意到一个回文串是可以通过一个长度小于等于这个串长度的一半的回文串添上一些字符然后复制得到的,也就是在自动机上向fa走,相当于treedp 每次都走显然会T,记录一个up,指向祖先中最下 ...
随机推荐
- console 有没有小伙伴跟我一样想知道这个对象呢
晚上看了会代码,没什么简单又好分享的 -0- 突然想到console这个对象,就把它打印了出来看看吧 ; for(var key in console){ i++; ){ document.write ...
- ABAP分享五 ALV修改单元格并将修改数据更新到数据表中示例1
*下面的代码是在alv字段中修改字段的内容,点击保存后就可以保存数据至数据表. TABLES: spfli. DATA: wa_fieldcat TYPE lvc_s_fcat , " 相 ...
- HTTP Error 500.19 - Internal Server Error 无法读取配置文件
将Code移动文件夹就报以下错误,http error 500.19 - internal server error. 项目文件下.vs=>config=>applicationhost. ...
- 设置tabBar的图片/高度/title颜色
实现了一下内容: 1.设置tabBarItem选中及非选中时的图片,图片充满item; 2.调整了 tabBar 高度; 3.改变了title颜色及位置. ------------代码如下: ---T ...
- MySQL日志简介
一.MySQL日志简介 二.错误日志 作用: 记录mysql数据库的一般状态信息及报错信息,是我们对于数据库常规报错处理的常用日志. 默认位置: $MYSQL_HOME/data/ 开启方式:(MyS ...
- PHP switch的写法
switch switch (expression) { case label1: expression = label1 时执行的代码 ; break; case label2: expressio ...
- Self Service Password 密码策略
1.在活动目录中新建一个用户,并赋予域管理员权限:2.拷贝conf目录下的config.inc.php为config.inc.local.php:3.按自己的实际情况及要求修改config.inc.l ...
- fiddler抓包的一些基本知识整理
fiddler常用命令:selelct xx: 高亮显示所有的text,js,image等响应类型?xxx:匹配所有url.protocol.host中包含xxx的会话=404:选择响应状态码为404 ...
- 08. Go 语言包(package)
Go 语言包(package) Go 语言的源码复用建立在包(package)基础之上.Go 语言的入口 main() 函数所在的包(package)叫 main,main 包想要引用别的代码,必须同 ...
- 从零开始学习java一般需要多长时间?
从零开始学习java一般需要多长时间? 其实学java一般要多久?因人而异,例如一个零基础的小白自学java,每天学习8个小时来算,而且在有学习资料的基础上,每天学习,从零到找到工作,起码要半年起步, ...