题意 : 输入n、m、k意思就是给你 m 个模式串,问你构建长度为 n 至少包含 k 个模式串的方案有多少种

分析 : ( 以下题解大多都是在和 POJ 2778 && POJ 1625 && HDU 2243 进行类比,如果没做过的话.......可能看不懂 )

这道题如果去对比之前做过的 POJ 2778 And HDU 2243 可以发现现在的难点在于如何找出至少包含 k 个模式串的,这里我们给每一个单词编号,对于在DP过程当中选中了这个单词就标记一下,但是问题是如何判断是否被重复选过以及如何标记?如果直接开在DP的维度上那是不可能的!(即开一个十维数组来记录每一个单词是否被选过),如果能将这十个维度压缩成一个维度多好啊!没错了,使用二进制,二进制的每一位代表每一个单词,0就是没被选,1就是被选,最多只需要十位便能记录这些信息,转化为十进制之后我们只要给DP再多添一个维度即可。那么代码怎么实现呢?只需要用到 | 操作符即可,这个操作符会把每一位的 1 进行叠加,相当于吧信息进行叠加!不过这里需要注意,在做POJ 1625 的时候是用一个矩阵来转移的,而这道题不能,因为我们还附加了一个选了哪几个单词这一个维度,如果全部笼统的映射到矩阵上的话是不行的!比如 G[i][j] 代表从 i 到 j 一步走完的可行方案,但是我们不知道这些方案到底走过了那些单词,所以需要一步步转移,如果把 POJ 1625 的代码不用矩阵来储存信息那要怎么写呢?如下( 如果你之前看过我 POJ 1625 的代码的话 )

        ; i<m; i++)
        ; j<ac.Size; j++){
//            for(int k=0; k<ac.Size; k++){
//                dp[i+1][k] += dp[i][j] * G[j][k];
//            }
            ; k<n; k++){
                int tmp = ac.Node[j].Next[k];
                if(!ac.Node[tmp].flag)
                    dp[i+][tmp] += dp[i][j];
            }
        }

所以在网上搜这道题的题解的时候,一开始我有点懵,为什么有四层for?这和用矩阵有什么区别?实际上矩阵写法完全可以写成如上所示!

因此总结一下就是 利用DP[i][j][k] 表示 DP[第几步][哪个节点结尾][当前选了哪些单词] = 方案数

这里有个大优化,因为我们的DP是一个向前的DP,这样的DP有一个优势,就是当 DP值 == 0 的时候将不会对后面有任何影响,直接continue便能减去大量的“枝”!

#include<string.h>
#include<stdio.h>
#include<queue>
using namespace std;
;
;
;
][][(<<)+];
];
struct Aho{
    struct StateTable{
        int Next[Letter];
        int fail, id;
    }Node[Max_Tot];
    int Size;
    queue<int> que;

    inline void init(){
        while(!que.empty()) que.pop();
        memset(Node[].Next, , ].Next));
        Node[].fail = Node[].id = ;
        Size = ;
    }

    inline void insert(char *s, int id){
        ;
        ; s[i]; i++){
            int idx = s[i] - 'a';
            if(!Node[now].Next[idx]){
                memset(Node[Size].Next, , sizeof(Node[Size].Next));
                Node[Size].fail = Node[Size].id = ;
                Node[now].Next[idx] = Size++;
            }
            now = Node[now].Next[idx];
        }
        Node[now].id |= (<<id);
    }

    inline void BuildFail(){
        Node[].fail = ;
        ; i<Letter; i++){
            ].Next[i]){
                Node[Node[].Next[i]].fail = ;
                que.push(Node[].Next[i]);
            }].Next[i] = ;
        }
        while(!que.empty()){
            int top = que.front(); que.pop();
            Node[top].id |= Node[Node[top].fail].id;
            ; i<Letter; i++){
                int &v = Node[top].Next[i];
                if(v){
                    que.push(v);
                    Node[v].fail = Node[Node[top].fail].Next[i];
                }else v = Node[Node[top].fail].Next[i];
            }
        }
    }
}ac;
];
int main(void)
{
    ; i<(<<); i++){
        cnt[i] = ;
        ; j<; j++){
            <<j))
                cnt[i]++;
        }
    }

    int n, m, k;
    while(~scanf("%d %d %d", &n, &m, &k)){
         && m== && k==) break;
        ac.init();
        ; i<m; i++){
            scanf("%s", S);
            ac.insert(S, i);
        }
        ac.BuildFail();

        ; i<=n; i++)
            ; j<ac.Size; j++)
                ; l<(<<m); l++)
                    dp[i][j][l] = ;

        dp[][][] = ;

        ; i<n; i++){
            ; j<ac.Size; j++){
                ; l<(<<m); l++){
                    ){
                        ; x<Letter; x++){///不用矩阵了,一步步转移
                            ;
                            int newj = ac.Node[j].Next[x];
                            int newl = (ac.Node[ newj ].id) | l;///加入了哪个新节点就应该去叠加状态!
                            dp[newi][newj][newl] += dp[i][j][l];
                            dp[newi][newj][newl] %= MOD;
                        }
                    }
                }
            }
        }

        ;
        ; i<(<<m); i++){
            if(cnt[i]>=k){
                ; j<ac.Size; j++){
                    ans = (ans + dp[n][j][i])%MOD;
                }
            }
        }

        printf("%d\n", ans%MOD);
    }
    ;
}

HDU 2825 Wireless Password ( Trie图 && 状态压缩DP )的更多相关文章

  1. HDU - 2825 Wireless Password(AC自己主动机+DP)

    Description Liyuan lives in a old apartment. One day, he suddenly found that there was a wireless ne ...

  2. hdu 4057 AC自己主动机+状态压缩dp

    http://acm.hdu.edu.cn/showproblem.php?pid=4057 Problem Description Dr. X is a biologist, who likes r ...

  3. HDU 2825 Wireless Password (AC自己主动机,DP)

    pid=2825">http://acm.hdu.edu.cn/showproblem.php? pid=2825 Wireless Password Time Limit: 2000 ...

  4. hdu 2825 Wireless Password(ac自己主动机&amp;dp)

    Wireless Password Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others ...

  5. [AC自己主动机+状压dp] hdu 2825 Wireless Password

    题意: 给n.m,k ,再给出m个单词 问长度为n的字符串.至少在m个单词中含有k个的组成方案有多少种. 思路: 因为m最大是10,所以能够採取状压的思想 首先建立trie图,在每一个单词的结束节点标 ...

  6. HDU 5418 Victor and World (状态压缩dp)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5418 题目大意:有n个结点m条边(有边权)组成的一张连通图(n <16, m<100000 ...

  7. hdu 5067 Harry And Dig Machine (状态压缩dp)

    题目链接 bc上的一道题,刚开始想用这个方法做的,因为刚刚做了一个类似的题,但是想到这只是bc的第二题, 以为用bfs水一下就过去了,结果MLE了,因为bfs的队列里的状态太多了,耗内存太厉害. 题意 ...

  8. HDU 4649 Professor Tian(反状态压缩dp,概率)

    本文出自   http://blog.csdn.net/shuangde800 题目链接:点击打开链接 题目大意 初始有一个数字A0, 然后给出A1,A2..An共n个数字,这n个数字每个数字分别有一 ...

  9. HDU - 2825 Wireless Password (AC自动机+状压DP)

    题目连接:http://acm.hdu.edu.cn/showproblem.php?pid=2825 题意:给一些字符串,构造出长度为n的字符串,它至少包含k个所给字符串,求能构造出的个数. 题解: ...

随机推荐

  1. 13.DoS防御----BeEF浏览器渗透----暴力破解之美杜莎---DNS指南

    DoS防御 启用ICMP,UDP,TCP泛洪过滤 登录路由器管理后台 高级-安全部分 BeEF浏览器渗透 用kali进行客户端攻击 钓鱼攻击 打开beef 浏览器打开beef cd /usr/shar ...

  2. DB.JDBC_jar_下载

    1.Download Microsoft JDBC Driver for SQL Server - SQL Server _ Microsoft Docs.html(https://docs.micr ...

  3. 100+ Python挑战性编程练习(2)

    熟能生巧,多撸代码多读书 https://github.com/zhiwehu/Python-programming-exercises/blob/master/100+%20Python%20cha ...

  4. Hive-java.lang.ClassNotFoundException: org.apache.hadoop.hive.contrib.serde2.MultiDelimitSerDe

    Task with the most failures(): ----- Task ID: task_1555476136794_8201_m_000000 URL: http://hadoop1:8 ...

  5. [转帖]解决K8S 安装只有 一直提示:kernel:unregister_netdevice: waiting for eth0 to become free. Usage count = 1 的方法

    Centos7 终端报Message from syslogd :kernel:unregister_netdevice https://www.jianshu.com/p/96d7e2cd9e99 ...

  6. 洛谷 P5662 纪念品 & [NOIP2019普及组] (dp,完全背包)

    传送门 解题思路 本题首先要明白,在每一天时,最优策略是先进行操作2(卖),再进行操作1(买),才能是利益最大化. 本题很显然当只有两天时,是一个完全背包,就是把当日价钱当做体积,把明日价格和今日价格 ...

  7. 如何将数据库导入到本地MySQL

    有两个方法:(1)在MySQL的客户端进行导入,比如: http://jingyan.baidu.com/article/6dad507517c11aa123e36ea0.html (2)方法:常用s ...

  8. MFC- socket 编程

    一.CAsyncSocket类 CAsyncSocket属于异步非阻塞类. CAsyncSocket类采用了windows socket中的WSAAsyncSelect模型.CAsyncSocket ...

  9. java创建对象的5种方法

    java是面向对象的,所以在使用中经常会去创建对象,而我们一般创建对象只会使用new关键字去创建,这里给大家总结一下在java中创建对象的5中方法: 使用new关键字 } → 调用了构造函数 使用Cl ...

  10. 17.Linux-CentOS系统OpenStack-Keystone同步数据库时报错

    问题描述:在同步Keystone数据库时报以下错误[root@controller ~]# su -s /bin/sh -c "keystone-manage db_sync" k ...