说在前面

me真的…觉得自己很棒棒
一个小时不到敲完了,提交然后WA,以为自己板子写错了,然而对照着之前的代码发现并没有错
然后me在花式TLE,RE,WA之后,确定是有一个地方搞成了NULL,然而逻辑上来说并不可能…
然后继续对照着网上的代码查错,换了各种写法,还是会RE

最后发现me数组开小了???心态爆炸


题目

BZOJ4044传送门

题目大意

给出一个仅由AGCT四个字符组成的目标串,您需要通过以下两种操作 通过一个初始为空的串 得到目标串
1. 在已有串的 最前面 或者 最后面 添加一个字符
2. 将已有串复制,并反向接在当前串后面(比如ACT,变换后为ACTTCA)
需要求出最少的操作次数

输入输出格式

输入格式:
第一行一个整数T,表示数据组数
接下来每行一组数据,包含一个字符串(仅由AGTC组成),表示目标串

输出格式:
当然是输出答案啦qwq
每组数据一行一个整数

数据范围:保证单串长不超过100000,保证正解可以过


解法

第二天一早就来填坑
可以发现,比起添加字符操作来说,倍增操作简直是太优秀了(次数少,增加长度多)
然而倍增只能得到一个回文串,因此我们需要找出目标串中的一个回文串S,使用(倍增+添加字符)的方法拼凑出S,剩下的部分则直接使用(添加字符)的方法进行拼凑

下面假设N是目标串长度
那么定义出dp数组:dp[i]表示拼凑出第i个回文串所需的最小代价,那么ans=min(ans,N−len[i]+dp[i])ans = min( ans , N - len[i]+dp[i] )
关于dp的转移,需要根据回文串的情况去讨论

  • 对于偶数回文串有:

    • xSSx的情况,看作是S在翻倍前先添加了一个x,即dp[xSSx] = dp[SS] + len[x]
    • SxxS的情况,同样的dp[SxxS] = (dp[S] + len[x])+1
    • 不考虑从原有回文串添加得来(S -> Sxx),因为这样步数为2,所以一定不如第一种转移优
  • 对于奇数回文串(假设当前回文串为xSx,这里x,y不一定只代表一个字符):

    • 直接令dp[xSx] = len[xSx]即可,因为即使有更优的策略,转移也会被其他转移覆盖

      • 如果xSx中,Sx是一个回文串,那么显然Sx长度为偶数,该种转移会被dp[Sx]覆盖
      • 如果在xSx中,存在一个偶回文串L且L的长度不超过xSx的一半。在这样的情况下,dp[xSx] = dp[L] + len[xSx] - len[L],再使用dp[xSx]去更新其他的dp值,实际相就相当于使用dp[L]去更新其他的dp值(或答案),因此这种转移也是不必要的(如果被更新方式是暴力填补空缺,显然。只考虑倍增更新:Q = xSx + xSx,即Q = xLyLx + xLyLx = x+(LyLxxLyL)+x,显然这种情况会被 偶数回文串LyLxxLyL通过在两边暴力添加x更新)

上文一直回避了一个问题,该怎样统计回文串?很明显是回文自动姬
对于偶数回文串通过S的转移,S的长度不能超过xSSx(SxxS)的一半,这个只需要再维护一个half_fail指针就可以了,具体看代码


下面是me再也不想看见的代码

/**************************************************************Problem: 4044User: IzumihanakoLanguage: C++Result: AcceptedTime:5880 msMemory:13028 kb
****************************************************************/#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std ;int T , N , Node_cnt , ans , f[100005] ;
char ss[100005] ;
struct Node{int len , id ;Node *ch[10] , *fail , *half_fail ;
//  charater_map :: A(1) C(2) G(3) T(4)
}w[200005] , *tw = w , *root0 , *root1 , *last ;void newNode( Node *&nd , int len ){nd = ++tw ; nd->id = ++Node_cnt ;nd->len = len ;nd->fail = nd->half_fail = NULL ;memset( nd->ch , 0 , sizeof( nd->ch ) ) ;
}Node *getFail( Node *tmp , int pos ){while( ss[ pos-tmp->len-1 ] != ss[pos] ) tmp = tmp->fail ;return tmp ;
}
//  charater_map :: A(1) C(2) G(3) T(4)
void Insert( const short &id , int pos ){Node *p = getFail( last , pos ) ;if( !p->ch[id] ){Node *tmp = getFail( p->fail , pos )->ch[id] , *&nd = p->ch[id] ;newNode( nd , p->len + 2 ) ;nd->fail = ( tmp ? tmp : root0 ) ;if( nd->len <= 2 ) nd->half_fail = nd->fail ;else{tmp = p->half_fail ;while( ss[ pos-tmp->len-1 ] != ss[pos] || ( tmp->len+2 ) * 2 > nd->len )// 最终fail为child, len比tmp大2tmp = tmp->fail ;nd->half_fail = tmp->ch[id] ;}}last = p->ch[id] ;
}int tp[100005] , sa[100005] ;
void Rsort(){for( int i = 1 ; i <= N ; i ++ ) tp[i] = 0 ;tp[0] = 2 ;// root0 and root1for( int i = 3 ; i <= Node_cnt ; i ++ ) tp[ w[i].len ] ++ ;//except root0 and root1 for( int i = 1 ; i <= N ; i ++ ) tp[i] += tp[i-1] ;for( int i = Node_cnt ; i >= 3 ; i -- ) sa[ tp[w[i].len]-- ] = i ;
}void solve(){for( int i = 1 ; i <= N ; i ++ )Insert( ss[i] , i ) ;Rsort() ;for( int i = 1 ; i <= Node_cnt ; i ++ )f[i] = w[i].len ; // memset巨慢for( int i = 3 ; i <= Node_cnt ; i ++ ){Node *nd = ( w + sa[i] ) ; int now = sa[i] ;if( !(nd->len&1) ){f[now] = min( f[now] , f[nd->half_fail->id] + nd->len/2 - nd->half_fail->len + 1 ) ;// SxxS = ( S+(x) )+1 = ( f(S)+len(x) )+1for( short k = 1 ; k <= 4 ; k ++ )if( nd->ch[k] ) f[nd->ch[k]->id] = min( f[nd->ch[k]->id] , f[now] + 1 ) ; // xSSx = (Sx)+1 = f(S)+1 + x = f(SS) + x }ans = min( ans , N - nd->len + f[now] ) ; // ...S... = len( ... ) + f(S) ;}
}
//  charater_map :: A(1) C(2) G(3) T(4)
void init(){tw = w ; Node_cnt = 0 ;ans = 0x3f3f3f3f ;newNode( root1 , -1 ) ; root1->fail = root1 ;newNode( root0 , 0  ) ; root0->fail = root1 ;last = root0 ;
}int main(){scanf( "%d" , &T ) ;while( T -- ){init() ;scanf( "%s" , ss + 1 ) ; N = strlen( ss + 1 ) ;for( int i = 1 ; i <= N ; i ++ )if( ss[i] == 'A' ) ss[i] = 1 ;else if( ss[i] == 'C' ) ss[i] = 2 ;else if( ss[i] == 'G' ) ss[i] = 3 ;else if( ss[i] == 'T' ) ss[i] = 4 ;solve() ;printf( "%d\n" , ans ) ;}
}

[BZOJ4044]-Virus synthesis-回文自动姬+DP相关推荐

  1. BZOJ4044 Luogu P4762 [CERC2014]Virus Synthesis (回文自动机、DP)

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

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

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

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

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

  4. bzoj 4044: [Cerc2014] Virus synthesis 回文树

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

  5. [加强版] Codeforces 835D Palindromic characteristics (回文自动机、DP)

    题目链接: https://codeforces.com/contest/835/problem/D 题意: 一个回文串是\(1\)-回文的,如果一个回文串的左半部分和右半部分一样且都是\(k\)-回 ...

  6. 【leetcode】最长回文子串(区间dp)

    给定一个字符串 s,找到 s 中最长的回文子串.你可以假设 s 的最大长度为 1000. 示例 1: 输入: "babad" 输出: "bab" 注意: &qu ...

  7. 回文串 --- 动态dp UVA 11584

    题目链接: https://cn.vjudge.net/problem/34398/origin 本题的大意其实很简单,就是找回文串,大致的思路如下: 1. 确定一个回文串,这里用到了自定义的chec ...

  8. Libre OJ 「BalticOI 2013」非回文数 数位dp

    传送门 文章目录 题意: 思路: 题意: 问[l,r][l,r][l,r]内有多少个数是非回文数,即数字中不存在连续几个数为回文数. l,r≤1e18l,r\le1e18l,r≤1e18 思路: 这么 ...

  9. leetcode 131. 分割回文串(dp+回溯)

    给你一个字符串 s,请你将 s 分割成一些子串,使每个子串都是 回文串 .返回 s 所有可能的分割方案. 回文串 是正着读和反着读都一样的字符串. 示例 1: 输入:s = "aab&quo ...

最新文章

  1. 为什么说,我们可能是宇宙中唯一的智慧生命?
  2. auth0的java-jwt_Spring boot + JWT 实现安全验证 ---auth0.jwt
  3. mac os 命令行下载
  4. ES6新特性之let和const命令
  5. Ipad 日程管理APP使用心得
  6. [PowerShell]人人都值得学一点PowerShell实现自动化(2)有哪些可用的场景及方式?
  7. Linux 命令之 env -- 显示系统的环境变量,定义执行命令时的环境变量
  8. zedgraph使用中的难题
  9. zabbix3.0.4监控mysql主从同步
  10. A1136 | 字符串处理、大整数运算
  11. 超过 40 款很有用而且很新的 jQuery 插件
  12. NG2-我们创建一个可复用的服务来调用英雄的数据
  13. Hadoop大数据组件简介
  14. maven阿里仓库配置教程
  15. 由于没有安装音量控制程序,WINDOWS无法在任务栏上显示音量控制,怎么解决?
  16. 自动阅读专业版第九次更新---原薅羊毛专业版
  17. 彻底搞懂Android文件存储---内部存储,外部存储以及各种存储路径解惑
  18. 数据存储与容灾实验 用Winhex恢复磁盘
  19. 如何给PDF文件添加页码
  20. 今日恐慌与贪婪指数为10 恐慌程度稍有上升

热门文章

  1. python下载文件并改名_Python 实现自动重命名网易云音乐下载文件
  2. 库克10年,苹果电池为何落后安卓手机?
  3. CVPR 2020 论文大盘点-图像质量评价篇
  4. 使用Flex+Cairngorm+AIR制作列车时刻表查询工具[连载三]
  5. python:实现将PDF转换为有声读物(附完整源码)
  6. 李航 统计学习方法 第二版 课后习题答案 机器学习
  7. 从MTK的scat文件谈ROM和RAM的分配,管理和问题解决(拷贝)
  8. 饥荒联机版 Don‘t Starve Together服务器架设
  9. C1—— cesium 离线开发去除在线图片自己添加背景图
  10. seraku智能android镜面,安卓智能镜面 边照镜子边看天气量体重