• 每日总结-05-19(AC自己主动机结束)


    今天下午讨论了一下校赛的题,最终最终拍板,把校赛的题目定下来了。

    然后今天A掉了4个AC自己主动机的题目。最终完毕了AC自己主动机专辑里面的15个题。至此AC自己主动机全然结束。

    明天开启线段树专题。

    。。。。

    ------------------------------------------------------------------------------------------------------------------------------------

    1,,hdu-2457-DNA repair

    题目:给出一些不合法的模式DNA串,给出一个原串,问最少须要改动多少个字符,使得原串中不包括非法串

    做法:把病毒串做成一个trie树。

    DP[i][j]:长度为i,在trie树上的状态为j。须要改变的最少的字符的个数。

    dp[i][j]=dp[i-1][k]+转移费用。

    #include<stdio.h>
    #include<algorithm>
    #include<iostream>
    #include<stdlib.h>
    #include<vector>
    #include<queue>
    #include<string.h>
    #include<math.h>
    using namespace std;
    #define LL __int64
    #define maxn 55
    const int maxnode=55*21;
    const int childnum=5;
    const int mod=1000000007;
    const int INF=99999999;
    struct ac_tree
    {
        int chd[maxnode][childnum];
        int val[maxnode];
        int fail[maxnode];
        int key[1<<11];
        int Q[maxnode];
        int ID[128];
        int sz;
        int dp[1100][maxnode];
        void init()
        {
            fail[0]=0;
            for(int i=0;i<childnum;i++)
            {
                ID[i]=i;
            }
            ID['A']=1;ID['G']=2;
            ID['C']=3;ID['T']=4;
        }
        void reset()
        {
            memset(chd,0,sizeof(chd));
            sz=1;
        }
        void insert(char str[],int k)
        {
            int p=0;
            int len=strlen(str);
            for(int i=0;i<len;i++)
            {
                int c=ID[str[i]];
                if(!chd[p][c])
                {
                    memset(chd[sz],0,sizeof(chd[sz]));
                    val[sz]=0;
                    chd[p][c]=sz++;
                }
                p=chd[p][c];
            }
            val[p]=k;
        }
        void ac_build()
        {
            int *s=Q,*e=Q;
            for(int i=1;i<childnum;i++)
            {
                if(chd[0][i])
                {
                    fail[chd[0][i]]=0;
                    *e++=chd[0][i];
                }
            }
            while(s!=e)
            {
                int u=*s++;
                if(val[fail[u]])val[u]+=val[fail[u]];
                for(int i=1;i<childnum;i++)
                {
                    int &v=chd[u][i];
                    if(v)
                    {
                        *e++=v;
                        fail[v]=chd[fail[u]][i];
                      //  val[v]=(val[v]+val[fail[v]]);
                    }
                    else v=chd[fail[u]][i];
                }
            }
        }
        int work(char str[])
        {
            int len=strlen(str);
            int i,j,k;
            for(i=0;i<=len;i++)
                for(j=0;j<sz;j++)dp[i][j]=INF;
            dp[0][0]=0;
            int cr,x;
            for(i=0;i<len;i++)
            {
                for(j=0;j<sz;j++)
                {
                    if(dp[i][j]==INF)continue;
                    for(k=1;k<childnum;k++)
                    {
                        cr=chd[j][k];
                        if(val[cr])continue;
                        x=dp[i][j];
                        if(k!=ID[str[i]])x++;
                        dp[i+1][cr]=min(dp[i+1][cr],x);
                    }
                }
            }
            int maxx=INF;
            for(j=0;j<sz;j++)
            {
                maxx=min(maxx,dp[len][j]);
            }
            if(maxx==INF)cout<<"-1"<<endl;
            else cout<<maxx<<endl;
        }
    }AC;
    char tmp[1550];
    int main()
    {
        AC.init();
        int n,m,k,x;
        int T;
        T=0;
        while(~scanf("%d",&n)&&(n))
        {
            T++;
            AC.reset();
            for(int i=1;i<=n;i++)
            {
    
                scanf("%s",tmp);
                AC.insert(tmp,1);
            }
            AC.ac_build();
            scanf("%s",tmp);
            printf("Case %d: ",T);
            AC.work(tmp);
        }
        return 0;
    }

    2,zoj-3228-Searching the String

    题目大意:给出一个字符串和若干个单词。问这些单词在字符串里面出现了多少次。单词前面为0表示这个单词可重叠出现。1为不可重叠出现。


    做法: 可重叠的非常优点理,就是AC自己主动机处理。不可重叠的就记录下上次这个单词出现的位置。假设上次出现的位置加上这个单词的长度小于等于当前位置的话,那么这个单词的次数就加一。否则就不加。

    注意:可能存在两个字符串相等,比較坑爹。。。

    #include<stdio.h>
    #include<algorithm>
    #include<iostream>
    #include<stdlib.h>
    #include<vector>
    #include<queue>
    #include<string.h>
    #include<math.h>
    using namespace std;
    #define LL __int64
    #define maxn 55
    const int maxnode=6*110000;
    const int childnum=27;
    const int mod=1000000007;
    const int INF=99999999;
    struct ac_tree
    {
        int chd[maxnode][childnum];
        int val[maxnode][2];
        int fail[maxnode];
        int last[maxnode];
        int num[maxnode][2];
        int *ans[maxnode];
        int key[1<<11];
        int Q[maxnode];
        int ID[128];
        int sz;
        void init()
        {
            fail[0]=0;
            for(int i=0;i<childnum;i++)
            {
                ID[i+'a']=i+1;
            }
        }
        void reset()
        {
            memset(chd,0,sizeof(chd));
            memset(num,0,sizeof(num));
            sz=1;
        }
        void insert(char str[],int k,int tt)
        {
            int p=0;
            int len=strlen(str);
            for(int i=0;i<len;i++)
            {
                int c=ID[str[i]];
                if(!chd[p][c])
                {
                    memset(chd[sz],0,sizeof(chd[sz]));
                    val[sz][tt]=0;
                    chd[p][c]=sz++;
                }
                p=chd[p][c];
            }
            val[p][tt]=len;
            last[p]=-1;
            ans[k]=&num[p][tt];
        }
        void ac_build()
        {
            int *s=Q,*e=Q;
            for(int i=1;i<childnum;i++)
            {
                if(chd[0][i])
                {
                    fail[chd[0][i]]=0;
                    *e++=chd[0][i];
                }
            }
            while(s!=e)
            {
                int u=*s++;
                //if(val[fail[u]])val[u]+=val[fail[u]];
                for(int i=1;i<childnum;i++)
                {
                    int &v=chd[u][i];
                    if(v)
                    {
                        *e++=v;
                        fail[v]=chd[fail[u]][i];
                      //  val[v]=(val[v]+val[fail[v]]);
                    }
                    else v=chd[fail[u]][i];
                }
            }
        }
        int work(char str[],int n)
        {
            int len=strlen(str);
            int root=0,key,tp,x;
            for(int i=0;i<len;i++)
            {
                tp=ID[str[i]];
                root=chd[root][tp];
                key=root;
                while(key!=0)
                {
                    if(val[key][0]!=0)num[key][0]++;
                    if(val[key][1]!=0)
                    {
                        if(last[key]<=i-val[key][1])
                        {
                            num[key][1]++;
                            last[key]=i;
                        }
                    }
                    key=fail[key];
                }
            }
            for(int i=1;i<=n;i++)
                printf("%d
    ",*ans[i]);
            puts("");
        }
    }AC;
    char tmp[1550];
    char as[110000];
    int main()
    {
        AC.init();
        int n,m,k,x;
        int T;
        T=0;
        while(~scanf("%s",as))
        {
            T++;
            AC.reset();
            scanf("%d",&n);
            for(int i=1;i<=n;i++)
            {
                scanf("%d %s",&k,tmp);
                AC.insert(tmp,i,k);
            }
            AC.ac_build();
            printf("Case %d
    ",T);
            AC.work(as,n);
        }
        return 0;
    }

    3,hdu-3341-Lost's revenge

    抄的解题报告,感觉说的非常具体。我就不赘余了。

     题意:给出一些病毒串,一个原串,问怎么调整原串的顺序使得跟最多的病毒串匹配

        抄解题报告:
        自己主动机+DP。设主串有na个A、nc个C、ng个G、nt个T,于是题意转化为用na个A、
        nc个C、ng个G、nt个T生成一个新串,使模式串匹配次数最大。

    先将模式串生成自己主动机
        〔trie图〕,然后在这上面进行DP。状态可表示为dp[d,s],d为自己主动机状态。
        s表示由ma个A、mc个C、mg个G、mt个T的生成串
        〔s可表示为ma*(nc+1)*(ng+1)*(nt+1)+mc*(ng+1)*(nt+1)+mg*(nt+1)+mt〕。
        转移为O(4),总复杂度O(500*11^4*4) 
        
        那种表示方法就是变进制吧

        直接DP(root,s)会超时
        Qinz说这题卡时紧
        我用他的那种dfs才干过。他是先dfs枚举出状态,然后对这个状态递推计算。好快

        比較奇妙,不用管顺序的,就记录个数

    #include<stdio.h>
    #include<algorithm>
    #include<iostream>
    #include<stdlib.h>
    #include<vector>
    #include<queue>
    #include<string.h>
    #include<math.h>
    using namespace std;
    #define LL __int64
    #define maxn 55
    const int maxnode=51*10;
    const int childnum=5;
    const int mod=1000000007;
    const int INF=99999999;
    struct ac_tree
    {
        int chd[maxnode][childnum];
        int val[maxnode];
        int fail[maxnode];
        int Q[maxnode];
        int ID[128];
        int sz;
        int dp[maxnode][14642];
        void init()
        {
            fail[0]=0;
            for(int i=0;i<childnum;i++)
            {
                ID[i+'a']=i+1;
            }
            ID['A']=1;ID['T']=2;
            ID['G']=3;ID['C']=4;
        }
        void reset()
        {
            memset(chd,0,sizeof(chd));
            memset(val,0,sizeof(val));
            sz=1;
        }
        void insert(char str[],int k)
        {
           // cout<<str<<endl;
            int p=0;
            int len=strlen(str);
            for(int i=0;i<len;i++)
            {
                int c=ID[str[i]];
                if(!chd[p][c])
                {
                    memset(chd[sz],0,sizeof(chd[sz]));
                    val[sz]=0;
                    chd[p][c]=sz++;
                }
                p=chd[p][c];
            }
            val[p]+=k;
            //cout<<p<<" "<<val[p]<<endl;
        }
        void ac_build()
        {
            int *s=Q,*e=Q;
            for(int i=1;i<childnum;i++)
            {
                if(chd[0][i])
                {
                    fail[chd[0][i]]=0;
                    *e++=chd[0][i];
                }
            }
            while(s!=e)
            {
                int u=*s++;
                if(val[fail[u]])val[u]+=val[fail[u]];
                for(int i=1;i<childnum;i++)
                {
                    int &v=chd[u][i];
                    if(v)
                    {
                        *e++=v;
                        fail[v]=chd[fail[u]][i];
                      //  val[v]=(val[v]+val[fail[v]]);
                    }
                    else v=chd[fail[u]][i];
                }
            }
        }
        int work(char str[])
        {
            int num[5];
            memset(num,0,sizeof(num));
            int len=strlen(str);
            for(int i=0;i<len;i++)num[ID[str[i]]]++;
            dp[0][0]=0;
            int tai,cr;
            int sum[6];
            sum[5]=1;
            sum[4]=num[4]+1;
            sum[3]=(num[3]+1)*sum[4];
            sum[2]=(num[2]+1)*sum[3];
            sum[1]=(num[1]+1)*sum[2];
            int a[5],i,j;
            int pt;
            memset(dp,-1,sizeof(dp));
            dp[0][0]=0;
            for(a[1]=0;a[1]<=num[1];a[1]++)
            for(a[2]=0;a[2]<=num[2];a[2]++)
            for(a[3]=0;a[3]<=num[3];a[3]++)
            for(a[4]=0;a[4]<=num[4];a[4]++)
            {
                if(a[1]+a[2]+a[3]+a[4]>=len)break;
                tai=0;
                for(i=1;i<=4;i++)tai+=a[i]*sum[i+1];
                for(i=0;i<sz;i++)
                {
                    if(dp[i][tai]==-1)continue;
                    for(j=1;j<childnum;j++)
                    {
                        if(a[j]+1>num[j])continue;
                        cr=chd[i][j];
                        pt=tai+sum[j+1];
                       // if(dp[cr][pt]==-1)dp[cr][pt]=dp[i][tai];
                        dp[cr][pt]=max(dp[cr][pt],dp[i][tai]+val[cr]);
                       // cout<<i<<" "<<j<<"->"<<cr<<" "<<pt<<" "<<dp[cr][pt]<<endl;
                    }
                }
            }
            pt=num[1]*sum[2]+num[2]*sum[3]+num[3]*sum[4]+num[4];
            int maxx=-1;
            for(i=0;i<sz;i++)
            {
                maxx=max(maxx,dp[i][pt]);
            }
            cout<<maxx<<endl;
        }
    }AC;
    char tmp[1550];
    char as[110000];
    int main()
    {
        AC.init();
        int n,m,k,x;
        int T;
        T=0;
        while(~scanf("%d",&n)&&n)
        {
            T++;
            AC.reset();
            for(int i=1;i<=n;i++)
            {
                scanf("%s",tmp);
                AC.insert(tmp,1);
            }
            AC.ac_build();
            scanf("%s",as);
            printf("Case %d: ",T);
            AC.work(as);
        }
        return 0;
    }

    4,hdu-3247-Resource Archiver

    题意:

    给你 n 个串。和 m 个病毒串。要把这 n 个串
    连起来来,能够重叠,但不能包括 m 个病毒串
    中的随意一个。求把 n 个串连起来的最小长度。

    做法:这个题目憋了我非常长时间,一直不知道怎么样处理。后来经过翻阅博客。最终悟出来点。

    把病毒串和非病毒串都标记在trie树上处理。然后病毒串的地方标记为病毒串,非病毒串的地方标记为是哪一个串。

    状态压缩一下。

    然后从每一个非病毒串的结尾開始bfs。

    map[i][j]:从i字符串的结尾。到j字符串的结尾的最短路径是多少。

    然后就能够DP了。

    dp[i][j]:已用的字符串为i状态,在trie树上的点为j状态。的最短路径。

    #include<stdio.h>
    #include<algorithm>
    #include<iostream>
    #include<stdlib.h>
    #include<vector>
    #include<queue>
    #include<string.h>
    #include<math.h>
    using namespace std;
    #define LL __int64
    #define maxn 205
    const int maxnode=100001;
    const int childnum=3;
    const int mod=1000000007;
    const int INF=99999999;
    struct list
    {
        int st;
        int x;
    }pp,qq;
    struct ac_tree
    {
        int chd[maxnode][childnum];
        int val[maxnode];
        int fail[maxnode];
        int Q[maxnode];
        int var[maxnode];
        int vis[maxnode];
        int dist[maxnode];
        int st[maxn];
        int ID[128];
        int sz;
        int maps[maxn][maxn];
        int ns;
        int dp[1<<11][maxn];
        void init()
        {
            fail[0]=0;
            for(int i=0;i<childnum;i++)
            {
                ID[i+'a']=i+1;
            }
            ID['0']=1;ID['1']=2;
        }
        void reset()
        {
            memset(chd,0,sizeof(chd));
            memset(val,0,sizeof(val));
            memset(var,0,sizeof(var));
            memset(maps,-1,sizeof(maps));
            sz=1;
        }
        void insert(char str[],int k,int ps)
        {
           // cout<<str<<endl;
            int p=0;
            int len=strlen(str);
            for(int i=0;i<len;i++)
            {
                int c=ID[str[i]];
                if(!chd[p][c])
                {
                    memset(chd[sz],0,sizeof(chd[sz]));
                    val[sz]=0;
                    chd[p][c]=sz++;
                }
                p=chd[p][c];
            }
            if(ps==0)
            {
                val[p]=k;
                var[p]=0;
            }
            else var[p]=1;
            //cout<<p<<" "<<val[p]<<endl;
        }
        void ac_build()
        {
            int *s=Q,*e=Q;
            for(int i=1;i<childnum;i++)
            {
                if(chd[0][i])
                {
                    fail[chd[0][i]]=0;
                    *e++=chd[0][i];
                }
            }
            while(s!=e)
            {
                int u=*s++;
                //if(val[fail[u]]==-1)val[u]=-1;
                for(int i=1;i<childnum;i++)
                {
                    int &v=chd[u][i];
                    if(v)
                    {
                        *e++=v;
                        fail[v]=chd[fail[u]][i];
                        val[v]=(val[v]|val[fail[v]]);
                        var[v]=(var[v]|var[fail[v]]);
                    }
                    else v=chd[fail[u]][i];
                }
            }
        }
        int bfs(int u)
        {
            queue<int>que;
            while(!que.empty())que.pop();
            int x=st[u];
            que.push(x);
            memset(dist,-1,sizeof(dist));
            dist[x]=0;
            while(!que.empty())
            {
                x=que.front();
                que.pop();
                for(int i=1;i<childnum;i++)
                {
                    int y=chd[x][i];
                    if(var[y])continue;
                    if(dist[y]<0)
                    {
                        dist[y]=dist[x]+1;
                        que.push(y);
                    }
                }
            }
            for(int i=0;i<ns;i++)
            {
                maps[u][i]=dist[st[i]];
                //cout<<u<<"->"<<i<<"="<<maps[u][i]<<endl;
            }
        }
        int work(int n)
        {
            st[0]=0;
            ns=1;
            for(int i=0;i<sz;i++)
                if(val[i])
                {
                    st[ns++]=i;
                    //cout<<ns-1<<" "<<val[st[ns-1]]<<endl;
                }
            for(int i=0;i<ns;i++)bfs(i);
            memset(dp,-1,sizeof(dp));
            dp[0][0]=0;
            int cr;
            for(int i=0;i<(1<<n);i++)
            {
                for(int j=0;j<ns;j++)
                {
                    if(dp[i][j]<0)continue;
                    for(int k=0;k<ns;k++)
                    {
                        if(maps[j][k]<0)continue;
                        cr=i|val[st[k]];
                        if(dp[cr][k]==-1)dp[cr][k]=dp[i][j]+maps[j][k];
                        else dp[cr][k]=min(dp[cr][k],dp[i][j]+maps[j][k]);
                       // cout<<cr<<" "<<k<<" "<<dp[cr][k]<<endl;
                    }
                }
            }
            int minn=-1;
            cr=(1<<n)-1;
            for(int i=0;i<ns;i++)
            {
                if(dp[cr][i]==-1)continue;
                if(minn<0)minn=dp[cr][i];
                minn=min(minn,dp[cr][i]);
            }
            cout<<minn<<endl;
        }
    
    }AC;
    char tmp[1550];
    int main()
    {
        AC.init();
        int n,m,k,x;
        int T;
        T=0;
        while(~scanf("%d%d",&n,&m)&&(n||m))
        {
            AC.reset();
            for(int i=1;i<=n;i++)
            {
                scanf("%s",tmp);
                AC.insert(tmp,1<<(i-1),0);
            }
            for(int i=1;i<=m;i++)
            {
                scanf("%s",tmp);
                AC.insert(tmp,1,1);
            }
            AC.ac_build();
            AC.work(n);
        }
        return 0;
    }























  • 相关阅读:
    C++卷积神经网络实例:tiny_cnn代码具体解释(7)——fully_connected_layer层结构类分析
    不使用while,for,if等实现加法
    JavaScript包管理器综述
    hdu4455 dp
    Leetcode_num2_Maximum Depth of Binary Tree
    拉开大变革序幕(下):分布式计算框架与大数据
    TCP/IP协议组学习笔记
    Linux(centos 6.5) 调用java脚本以及定时运行的脚本实例及配置文件具体解释
    UVA11770
    C++再次理解虚表
  • 原文地址:https://www.cnblogs.com/blfbuaa/p/6881983.html
Copyright © 2020-2023  润新知