zoukankan      html  css  js  c++  java
  • 修改串

    我是传送门

    AC自动机+DP

    对于AC自动机的bfs,这里加了一点改进。

    • 引入了一个叫危险结点的东西,所谓危险结点,就是在字典树中以这个点结尾的字符串,是包含模式串的。

    • 如果某个点p没有了子节点,辣么我们需要将点p的子节点指向p的失败指针的子节点,这样是为了当穷途末路到达模式串的末尾时,就可以到一个可以查找的地方

    • 值得注意的就是,如果一个点x,他的儿子son,x的失败指针为j,由失败指针的定义可知,s[j]为s[x]的后缀,所以如果j也有一个和son字符一样的儿子,那么,son的失败指针就是就是j的儿子啦!这样是满足失败指针的定义的。

    • 如果某个点的失败指针是危险节点,那么这个点也要标记为危险结点

    对于DP

    • f[i][j]表示原字符串第i位,字典树上的结点j,当i的后缀与j到跟组成的字符串完全匹配的最小修改值

    • 注意如果这个点是危险结点,那么就不能更新f[i][j]了,因为如果转移了,那就不符合题目要求了

    • 这个转移方程很好想,就是f[i+1][son]=f[i][j]+(a[i+1]!=k),k就是son的字符,son是j的儿子,根据定义,就很好理解啦!

    • 答案就是f[n][i](i为树上所有的节点)

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    char s[60],change[1100];
    int slen,tot,n;
    struct char_tree{int son[5],end,fail;}tr[110000];
    void clean(int x)
    {
    	tr[x].end=0;tr[x].fail=-1;
    	memset(tr[x].son,-1,sizeof(tr[x].son));
    }
    int id(char c)
    {
    	if(c=='A')return 1;
    	else if(c=='C')return 2;
    	else if(c=='G')return 3;
    	else return 4;
    }
    void build_tree(int root)
    {
    	int x=root;
    	for(int i=1;i<=slen;i++)
    	{
    		int j=id(s[i]);
    		if(tr[x].son[j]==-1)tr[x].son[j]=++tot,clean(tot);
    		x=tr[x].son[j];
    	}
    	tr[x].end++;
    }
    int head,tail,list[2100000];
    void bfs()
    {
    	head=1;tail=1;memset(list,0,sizeof(list));
    	while(head<=tail)
    	{
    		int x=list[head];
    		for(int i=1;i<=4;i++)
    		{
    			int child=tr[x].son[i];
    			if(child==-1)
    			{
    				if(x==0)tr[x].son[i]=0;
    				else tr[x].son[i]=tr[tr[x].fail].son[i];
    				continue;
    			}
    			if(x==0)tr[child].fail=0;
    			else
    			{
    				int j=tr[x].fail;
    				while(j!=-1)
    				{
    					if(tr[j].son[i]!=-1)
    					{
    						tr[child].fail=tr[j].son[i];
    						int tmp=tr[j].son[i];if(tr[tmp].end!=0)tr[child].end=1;
    						break;
    					}
    					j=tr[j].fail;
    				}
    				if(j==-1)tr[child].fail=0;
    			}
    			list[++tail]=child;
    		}
    		head++;
    	}
    }
    int f[2100][2100];
    int DP()
    {
    	for(int i=0;i<=n;i++)for(int j=0;j<=tot;j++)f[i][j]=1e9;f[0][0]=0;
    	for(int i=0;i<n;i++)
    	{
    		for(int j=0;j<=tot;j++)
    		{
    			if(f[i][j]==1e9)continue;
    			for(int k=1;k<=4;k++)
    			{
    				int child=tr[j].son[k];
    				if(tr[child].end!=0)continue;
    				f[i+1][child]=min(f[i+1][child],f[i][j]+(id(change[i+1])!=k));
    			}
    		}
    	}
    	int ans=1e9;
    	for(int i=0;i<=tot;i++)ans=min(ans,f[n][i]);
    	if(ans==1e9)ans=-1;
    	return ans;
    }
    int main()
    {
    	int t=0;
    	while(scanf("%d",&n)!=EOF)
    	{
    		if(n==0)break;
    		t++;clean(0);
    		for(int i=1;i<=n;i++)
    		{
    			scanf("%s",s+1);slen=strlen(s+1);
    			build_tree(0);
    		}
    		bfs();
    		scanf("%s",change+1);n=strlen(change+1);
    		printf("Case %d: %d
    ",t,DP());
    	}
    	return 0;
    }
    
  • 相关阅读:
    制作centos镜像,启动镜像可以访问本地百度页面
    docker配置镜像加速后报错 系统 CentOS7
    代理方式获取天气预报信息
    周边分析-距离计算
    mysql随笔
    mysql笔记
    树形结构表的存储【转自:http://www.cnblogs.com/huangfox/archive/2012/04/11/2442408.html】
    Mysql中 in 和 exists 区别
    CPU飙高,系统性能问题如何排查?
    位运算的常见操作
  • 原文地址:https://www.cnblogs.com/candy067/p/11399435.html
Copyright © 2011-2022 走看看