zoukankan      html  css  js  c++  java
  • HDU 2825

    下午连续看了两题的AC自动机+DP题,发现都有点规律了,都是由trie图循环赋值,按照结点一步步向外推的,而且状态设的也很相似。。。

    dp[i][j][k],一开始以为至少k个是可以相同的,其实这k个串应该是不同的,于是就可以按照二进制压缩这M个串,1表示选上了这个串。注意一下fail指向的结点要与当前自身的选串的状态或上就可以了。为当前处于i状态,前j个字符。

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #include <climits>
    #include <string.h>
    #include <queue>
    #include <cmath>
    #include <map>
    #include <vector>
    #define LL  __int64
    using namespace std;
    
    const int dictsize=26;
    const int MOD =20090717;
    const int Maxn=150;
    const int root=0;
    const int state=(1<<10)-1;
    int head,tail;
    int que[Maxn];
    struct Node {
        int fail,next[dictsize];
        int tag;
        void initial(){
            fail=-1,tag=false;
            for(int i=0;i<dictsize;i++) next[i]=-1;
        }
    }trie[Maxn];
    int tot,n,m,l;
    char str[15];
    int dp[Maxn][26][state+1];
    
    void Insert_trie(int s){
        int p=0,i=0;
        while(str[i]){
            if(trie[p].next[str[i]-'a']==-1) trie[p].next[str[i]-'a']=++tot;
            p=trie[p].next[str[i]-'a'];
            i++;
        }
        trie[p].tag=(1<<s);
    }
     
    void build_ac(){
        que[tail++]=root;
        int i,tmp,p;
        while(head!=tail){
            tmp=que[head++];
            p=-1;
            for(int i=0;i<dictsize;i++){
                if(trie[tmp].next[i]!=-1){
                    if(tmp==root) trie[trie[tmp].next[i]].fail=root;
                    else{
                        p=trie[tmp].fail;
                        while(p!=-1){
                            if(trie[p].next[i]!=-1){
                                trie[trie[tmp].next[i]].fail=trie[p].next[i];
                                break;
                            }
                            p=trie[p].fail;
                        }
                        if(p==-1){
                            trie[trie[tmp].next[i]].fail=root;
                        }
                    }
                    trie[trie[tmp].next[i]].tag|=trie[trie[trie[tmp].next[i]].fail].tag;
                    que[tail++]=trie[tmp].next[i];
                }
                else{   //trie[tmp].next[i]==-1
                    if(tmp==root) trie[tmp].next[i]=root;
                    else{
                        p=trie[tmp].fail;
                        while(p!=-1){
                            if(trie[p].next[i]!=-1){
                                trie[tmp].next[i]=trie[p].next[i];
                                break;
                            }
                            p=trie[p].fail;
                        }
                        if(p==-1){
                            trie[tmp].next[i]=root;
                        }
                    }
                }
            }
        }
    }
    
    bool ok(int s,int k){
        int c=0;
        while(s){
            if(s&1) c++;
            s>>=1;
        }
        if(c>=k) return true;
        return false;
    }
    
    int main(){
        while(scanf("%d%d%d",&n,&m,&l)&&n||m||l){
            tot=head=tail=0;
            for(int i=0;i<110;i++)
            trie[i].initial();
            for(int i=0;i<m;i++){
                scanf("%s",str);
                Insert_trie(i);
            }
            build_ac();
            memset(dp,0,sizeof(dp));
            dp[0][0][0]=1;
            int alstate=(1<<m)-1,son;
            for(int j=0;j<=n;j++){
                for(int i=0;i<=tot;i++){
                    for(int k=0;k<=alstate;k++){
                        if(dp[i][j][k]>0){
                            for(int e=0;e<dictsize;e++){
                                son=trie[i].next[e];
                                dp[son][j+1][trie[son].tag|k]=(dp[son][j+1][trie[son].tag|k]+dp[i][j][k])%MOD;
                            }
                        }
                    }
                }
            }
            int ans=0;
            for(int i=0;i<=tot;i++){
                for(int k=0;k<=alstate;k++){
                    if(ok(k,l)){
                        ans=(ans+dp[i][n][k])%MOD;
                    }
                }
            }
            printf("%d
    ",ans);
        }
        return 0;
    }
    View Code
  • 相关阅读:
    开篇有益-解析微软微服务架构eShopOnContainers(一)
    复杂而艰辛的重构之路--起步
    Visual Studio 我的插件
    【翻译】使用Visual Studio创建Asp.Net Core MVC (一)
    【翻译】使用Visual Studio在Azure上部署Asp.Net Core Web应用
    【翻译】在Visual Studio中使用Asp.Net Core MVC创建第一个Web Api应用(二)
    【翻译】在Visual Studio中使用Asp.Net Core MVC创建你的第一个Web API应用(一)
    【翻译】在Mac上使用VSCode创建你的第一个Asp.Net Core应用
    【翻译】Asp.net Core介绍
    新的一年订个小目标,比如每周更新1-2篇博文
  • 原文地址:https://www.cnblogs.com/jie-dcai/p/4311833.html
Copyright © 2011-2022 走看看