zoukankan      html  css  js  c++  java
  • Luogu4762 [CERC2014]Virus synthesis

    Description

    link

    给定一个字符串,求通过以下两种方式最少用几次就可以构造出来它

    (1.) 在当前串尾添加任意一个字符

    (2.) 在串开头或末尾加一个当前的逆串

    Solution

    首先发现 (2) 操作就是可以把一个偶数长度的回文串通过较少次构造出来

    对这个给定的串建 (PAM) 吧,顺便求一下 (trans) 指针

    然后在 (PAM) 上面 (dp)

    直接从偶根 (bfs) (像 (AC) 自动机构建 (fail) 指针一样)

    (f_i) 为构造出来当前的串至少需要多少次操作

    然后 (ans=minlimits _ {i=2} ^{tot} n-len_i+f_i)

    转移分为以下两种:

    (1.) 当前串的长度(len_i)

    (2.) 从自动机上面直接转移 (f_i=min(f_i,f_{fail_i}+1))

    (3.)(trans) 指针上面转移

    [f_i=min(f_i,f_{trans_i} +1 +frac {len_i}{2}-len_{trans_i}) ]

    (补齐前缀然后复制)

    一坑点:(ans) 记得初始最大值设成 (n)

    Code

    #include<bits/stdc++.h>
    using namespace std;
    namespace yspm{
    	inline int read()
    	{
    		int res=0,f=1; char k;
    		while(!isdigit(k=getchar())) if(k=='-') f=-1;
    		while(isdigit(k)) res=res*10+k-'0',k=getchar();
    		return res*f;
    	}
    	const int N=1e5+10;
    	int ans;
    	struct PAM{
    		int t[N],fail[N],ch[N][4],tot,las,n,len[N],f[N];
    		char s[N];
    		inline void init()
    		{			
    			for(int i=0,j;i<=tot;++i) 
    			{
    				for(j=0;j<4;++j) ch[i][j]=0;
    				t[i]=0; f[i]=0; fail[i]=0; len[i]=0;
    			}
    			ans=2e9+10; fail[0]=fail[1]=tot=1; len[1]=-1; las=0;
    			return ;
    		}
    		inline void extend(int i)
    		{
    			int c=s[i]-'A',p=las;
    			while(s[i-len[p]-1]!=s[i]) p=fail[p];
    			if(ch[p][c]) return las=ch[p][c],void();
    			int y=++tot,x=fail[p];
    			while(s[i-len[x]-1]!=s[i]) x=fail[x];
    			len[y]=len[p]+2; fail[y]=ch[x][c]; las=ch[p][c]=y; 
    			if(len[y]<=2) return t[y]=fail[y],void();
    			int q=t[p]; while(len[q]*2+4>len[y]||s[i-len[q]-1]!=s[i]) q=fail[q];
    			t[y]=ch[q][c];
    			return ;
    		}
    		inline void work()
    		{
    			queue<int> q; for(int i=2;i<=tot;++i) f[i]=len[i];
    			for(int i=0;i<4;++i) if(ch[0][i]) q.push(ch[0][i]);
    			while(!q.empty())
    			{
    				int fr=q.front(); q.pop();
    				f[fr]=min(f[fr],f[t[fr]]+1+len[fr]/2-len[t[fr]]);
    				ans=min(ans,n-len[fr]+f[fr]); 
    				for(int i=0;i<4;++i)
    				{
    					if(!ch[fr][i]) continue;
    					f[ch[fr][i]]=min(f[ch[fr][i]],f[fr]+1); q.push(ch[fr][i]);
    				}
    			} return ;
    		}
    	};
    	PAM a;
    	inline char c(char p)
    	{
    		if(p=='A') return 'A';
    		if(p=='G') return 'B';
    		if(p=='C') return 'C';
    		if(p=='T') return 'D';
    		else return 0;
    	}
    	inline void work()
    	{
    		scanf("%s",a.s+1); a.init(); a.s[0]='#';
    		int len=strlen(a.s+1); a.n=len; 
    		for(int i=1;i<=len;++i) a.s[i]=c(a.s[i]),a.extend(i);
    		a.work(); ans=min(ans,len);
    		printf("%d
    ",ans); 
    		return ;
    	}
    	signed main()
    	{
    		int T=read(); while(T--) work();
    		return 0;
    	}
    }
    signed main(){return yspm::main();} 
    
  • 相关阅读:
    【12】简单SQL语句
    【11】分离与附加
    【10】约束
    CSS深入理解学习笔记之vertical-align
    CSS深入理解学习笔记之relative
    CSS深入理解学习笔记之z-index
    CSS深入理解学习笔记之margin
    CSS深入理解学习笔记之padding
    CSS深入理解学习笔记之border
    网页结构与表现原则
  • 原文地址:https://www.cnblogs.com/yspm/p/13297026.html
Copyright © 2011-2022 走看看