zoukankan      html  css  js  c++  java
  • hdu2457(最少替换多少个字符使主串不包含模式串)ac自动机+dp

    题:http://acm.hdu.edu.cn/showproblem.php?pid=2457

    题意:给定n个模式串,给定一个主串,问最替换掉多少个字符使主串不包含模式串或输出“-1”表示没有可行的方案;

    分析:给n个模式串建立ac自动机,考虑dp[i][j],表示长度为 i , j 节点变换为主串前 i 个的最小操作数,j节点要转换必须使当前节点为“安全点”,即end[trie[i][j]]==0;

       dp转化就只要不是自己就要在转移过程中+1,i 位置取min 给下一位i+1

    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    #include<cstring>
    #include<queue>
    using namespace std;
    typedef long long ll;
    const int M=2e3+3;
    const int maxn=4;
    const int inf=0x3f3f3f3f;
    int dp[M][M];
    char s[M];
    struct ac{
        int trie[M][maxn],fail[M];
        bool end[M];
        int tot,root;
        int newnode(){
            for(int i=0;i<maxn;i++)
                trie[tot][i]=-1;
            end[tot++]=0;
            return tot-1;
        }
        void init(){
            memset(end,false,sizeof(end));
            tot=0;
            root=newnode();
        }
        int getid(char c){
            if(c=='A')
                return 0;
            if(c=='G')
                return 1;
            if(c=='T')
                return 2;
            if(c=='C')
                return 3;
        }
        void insert(char buf[]){
            int now=root,len=strlen(buf);
            for(int i=0;i<len;i++){
                int id=getid(buf[i]);
                if(trie[now][id]==-1)
                    trie[now][id]=newnode();
                now=trie[now][id];
            }
            end[now]=true;
        }
        void getfail(){
            queue<int>que;
            while(!que.empty())
                que.pop();
            fail[root]=root;
            for(int i=0;i<maxn;i++){
                if(trie[root][i]==-1)
                    trie[root][i]=root;
                else{
                    fail[trie[root][i]]=root;
                    que.push(trie[root][i]);
                }
            }
            while(!que.empty()){
                int now=que.front();
                que.pop();
                if(end[fail[now]])
                    end[now]=true;
                for(int i=0;i<maxn;i++){
                    if(trie[now][i]!=-1){
                        fail[trie[now][i]]=trie[fail[now]][i];
                        que.push(trie[now][i]);
                    }
                    else
                        trie[now][i]=trie[fail[now]][i];
                }
            }
        }
    }AC;
    int main(){
        int n,t=0;
        while(~scanf("%d",&n)&&n){
            AC.init();
            for(int i=0;i<n;i++){
                scanf("%s",s);
                AC.insert(s);
            }
            AC.getfail();
            
                
            scanf("%s",s);
            int len=strlen(s);
            for(int i=0;i<=len;i++)
                for(int j=0;j<AC.tot;j++)
                    dp[i][j]=inf;
            dp[0][AC.root]=0;
            for(int i=0;i<len;i++)
                for(int j=0;j<AC.tot;j++)
                    if(dp[i][j]<inf){
                        for(int k=0;k<maxn;k++){
                            int now=AC.trie[j][k];
                            if(AC.end[now])
                                continue;
                        //    cout<<now<<"!!"<<endl;
                            int id=AC.getid(s[i]);
                            int add=0;
                            if(id!=k)
                                add++;
                            dp[i+1][now]=min(dp[i+1][now],dp[i][j]+add);
                        //    cout<<dp[i+1][now];
                        }
                    }
            int ans=inf;
            for(int i=0;i<AC.tot;i++){
                ans=min(ans,dp[len][i]);
                
            }
                
            printf("Case %d: ",++t);
            if(ans==inf)
                puts("-1");
            else
                printf("%d
    ",ans);
        }
        return 0;
    }
    View Code
  • 相关阅读:
    马云演讲:给自己一个梦想,给自己一个承诺,给自己一个坚持!
    转:如何成为一个伟大的开发者
    数据挖掘之七种常用的方法
    windows命令行
    100万亿意味着什么?
    ubuntu环境配置
    Ubuntu runlevel修改
    Ubuntu 用户及组管理
    Git学习笔记
    Git详解之三 Git分支
  • 原文地址:https://www.cnblogs.com/starve/p/12371877.html
Copyright © 2011-2022 走看看