zoukankan      html  css  js  c++  java
  • Bzoj4044 Virus synthesis

    题意

    你要用 (ATGC) 四个字母用两种操作拼出给定的串:

    1. 将其中一个字符放在已有串开头或者结尾
    2. 将已有串复制,然后 (reverse) ,再接在已有串的头部或者尾部

    一开始已有串为空。求最少操作次数。
    (lenle100000)

    Sol

    首先有个结论
    每次形成偶数长度回文串的最后一步一定是操作 (2)
    那么考虑一个 (DP)
    (f[i]) 表示形成 (i) 表示的字符串需要的最少步数
    可以去掉首和尾转移来,可以由它的一个前缀或者后缀转移来
    如果是个偶数长度的字符串
    可以由某个长度小于等于它一半的字符串增长到它的长度后翻倍而来
    可以由它去掉首尾的串一步转移而来,因为去掉首位仍然是偶数长度而且形成偶数长度回文串的最后一步一定是操作 (2)

    那么直接用回文树实现
    求某个长度小于等于它一半的字符串直接建树的时候暴力跳一下(雾

    # include <bits/stdc++.h>
    # define IL inline
    # define RG register
    # define Fill(a, b) memset(a, b, sizeof(a))
    using namespace std;
    typedef long long ll;
    
    IL int Input(){
    	RG int x = 0, z = 1; RG char c = getchar();
    	for(; c < '0' || c > '9'; c = getchar()) z = c == '-' ? -1 : 1;
    	for(; c >= '0' && c <= '9'; c = getchar()) x = (x << 1) + (x << 3) + (c ^ 48);
    	return x * z;
    }
    
    const int maxn(1e5 + 5);
    
    int f[maxn], son[4][maxn], trans[666], half[maxn], len[maxn], fa[maxn], num[maxn], tot, last, pre[maxn];
    char s[maxn];
    
    IL void Init(){
    	for(RG int i = 0; i <= tot; ++i){
    		len[i] = fa[i] = half[i] = 0;
    		for(RG int j = 0; j < 4; ++j) son[j][i] = 0;
    	}
    	fa[0] = fa[1] = 1, len[1] = -1, tot = 1, last = 0;
    }
    
    IL void Extend(RG int pos, RG int c){
    	RG int p = last;
    	while(s[pos - len[p] - 1] != s[pos]) p = fa[p];
    	if(!son[c][p]){
    		RG int np = ++tot, q = fa[p];
    		while(s[pos - len[q] - 1] != s[pos]) q = fa[q];
    		len[np] = len[p] + 2, fa[np] = son[c][q];
    		son[c][p] = np, pre[np] = p;
    		if(s[pos - len[half[p]] - 1] == s[pos]) half[np] = son[c][half[p]];
    		else half[np] = fa[np];
    		while((len[half[np]] << 1) > len[np]) half[np] = fa[half[np]];
    	}
    	last = son[c][p];
    }
    
    int main(){
    	trans['C'] = 1, trans['G'] = 2, trans['T'] = 3;
    	for(RG int t = Input(), n = 0; t; --t){
    		Init(), scanf(" %s", s + 1), n = strlen(s + 1);
    		for(RG int i = 1; i <= n; ++i) Extend(i, trans[s[i]]);
    		RG int ans = n;
    		for(RG int i = 2; i <= tot; ++i){
    			f[i] = min(len[i], f[fa[i]] + len[i] - len[fa[i]]);
    			if(len[i] & 1) f[i] = min(f[pre[i]] + 2, f[i]);
    			else{
    				f[i] = min(f[i], pre[i] ? f[pre[i]] + 1 : 2);
    				f[i] = min(f[i], f[half[i]] + (len[i] >> 1) - len[half[i]] + 1);
    			}
    			ans = min(ans, f[i] + n - len[i]);
    		}
    		printf("%d
    ", ans);
    	}
    	return 0;
    }
    
    
  • 相关阅读:
    LVS/NAT 配置
    LVS 介绍
    Nagios 服务安装
    Mysql 主从复制搭建
    GitHub托管BootStrap资源汇总
    基于bootstrap的datatable控件
    微信在线客服系统-微信公众平台开发
    UI Prototype Design IDE( 界面原型设计工具 )
    vlc多功能播放器
    javaC#php主流语言实现FMS流媒体传输协议RTMP的开源组件
  • 原文地址:https://www.cnblogs.com/cjoieryl/p/9153725.html
Copyright © 2011-2022 走看看