• 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
  • 相关阅读:
    Envoy
    Redis 使用总结
    kafka(一)
    docker搭建kafka环境&&Golang生产和消费
    docker-composer +Grafana+Prometheus系统监控之Redis
    Docker基础命令
    connection pool exhausted
    golang 单元测试&&性能测试
    golang http 中间件
    golang 函数的特殊用法
  • 原文地址:https://www.cnblogs.com/jie-dcai/p/4311833.html
Copyright © 2020-2023  润新知