传送门:点击打开链接

题意:有个密码长度为n,现在有m个魔力单词,要求密码中魔力单词的种类数>=k,问这种密码的种类数。

思路:和之前一样,我们会想到AC自动机去压缩状态,把状态给简化。然后我们就会想到一个问题,,因为一种种类实际上可能会出现很多次,但是统计的时候只统计一次,所以用普通的dp可能就做不到了,那么我们就必须考虑复杂度更高的方法,又看到m<=10,我们自然的想到了状压。因为一个节点可能是多个单词的结尾,所以用状压就刚好能表示出多个单词结尾的情况了,非常的巧妙~

但是这题也有两个很容易TLE的问题,,首先是一个超级剪枝,,虽然已经是第二次遇到这个问题了,但还是一开始没想到。

因为我们的dp是属于向前dp的类型,这种dp有一个非常好的优势,那就是如果当前状态的种类数为0,那么这个状态对后面就没有任何作用,可以直接剪枝。这样我们就能减去非常多的情况了。

其次,就是memset初始化的时候,如果组数比较多可能会超时,改成for循环去填充就行。。

#include<map>
#include<set>
#include<cmath>
#include<ctime>
#include<stack>
#include<queue>
#include<cstdio>
#include<cctype>
#include<string>
#include<vector>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<functional>
#define fuck(x) cout<<"["<<x<<"]"
#define FIN freopen("input.txt","r",stdin)
#define FOUT freopen("output.txt","w+",stdout)
using namespace std;
typedef long long LL;/*MX为总长度*/
const int MN = 25 + 5;
const int MX = 2e2 + 5;
const int mod = 20090717;
const int P = 26;LL dp[2][1 << 10][MX];struct AC_machine {int rear, root, m;int Next[MX][P], Fail[MX], End[MX];void Init(int _m) {m = _m;rear = 0;root = New();}int New() {End[rear] = 0;for(int i = 0; i < P; i++) {Next[rear][i] = -1;}return rear++;}void Add(char *A, int u) {int now = root, n = strlen(A);for(int i = 0; i < n; i++) {int id = A[i] - 'a';if(Next[now][id] == -1) {Next[now][id] = New();}now = Next[now][id];}End[now] |= 1 << u;}void Build() {queue<int>Q;Fail[root] = root;for(int i = 0; i < P; i++) {if(Next[root][i] == -1) {Next[root][i] = root;} else {Fail[Next[root][i]] = root;Q.push(Next[root][i]);}}while(!Q.empty()) {int u = Q.front(); Q.pop();End[u] |= End[Fail[u]];for(int i = 0; i < P; i++) {if(Next[u][i] == -1) {Next[u][i] = Next[Fail[u]][i];} else {Fail[Next[u][i]] = Next[Fail[u]][i];Q.push(Next[u][i]);}}}}LL Solve(int N, int K) {int cur = 0, cnxt = 1;for(int S = 0; S < (1 << m); S++) {for(int j = 0; j < rear; j++) {dp[cur][S][j] = 0;}}dp[cur][0][0] = 1;for(int i = 1; i <= N; i++) {for(int S = 0; S < (1 << m); S++) {for(int j = 0; j < rear; j++) {dp[cnxt][S][j] = 0;}}for(int S = 0; S < (1 << m); S++) {for(int j = 0; j < rear; j++) {if(dp[cur][S][j]) {for(int k = 0; k < P; k++) {int nxt = Next[j][k];dp[cnxt][S | End[nxt]][nxt] += dp[cur][S][j];dp[cnxt][S | End[nxt]][nxt] %= mod;}}}}swap(cur, cnxt);}LL ans = 0;for(int S = 0; S < (1 << m); S++) {int cnt = 0;for(int i = 0; i < m; i++) {if(S >> i & 1) cnt++;}if(cnt < K) continue;for(int j = 0; j < rear; j++) {ans += dp[cur][S][j];ans %= mod;}}return ans;}
} AC;char word[MX];int main() {int n, m, k; //FIN;while(~scanf("%d%d%d", &n, &m, &k), n) {AC.Init(m);for(int i = 0; i < m; i++) {scanf("%s", word);AC.Add(word, i);}AC.Build();printf("%I64d\n", AC.Solve(n, k));}return 0;
}

AC自动机+状压dp hdu2825 Wireless Password相关推荐

  1. HDU - 2825 Wireless Password(AC自动机+状压dp)

    题目链接:点击查看 题目大意:给出 m 个匹配串,问长度为 n 的字符串中,至少包含 k 个匹配串(可重叠)的字符串有多少个 题目分析:考虑到n,m,k都特别小,所以可以先用AC自动机将状态关系转移出 ...

  2. HDU - 2825 Wireless Password (AC自动机 + 状压dp)

    题目链接 题意 求至少包含KKK个给定字符串长度为NNN的字符串 思路 把所有可能的字符串建AC自动机,遍历所有节点dp[i][j][k]dp[i][j][k]dp[i][j][k] 表示以节点jjj ...

  3. 【hdu2825】ac自动机 + 状压dp

    传送门 题目大意: 给你一些密码片段字符串,让你求长度为n,且至少包含k个不同密码片段串的字符串的数量. 题解: 因为密码串不多,可以考虑状态压缩 设dp[i][j][sta]表示长为i的字符串匹配到 ...

  4. hdu 6086 -- Rikka with String(AC自动机 + 状压DP)

    题目链接 Problem Description As we know, Rikka is poor at math. Yuta is worrying about this situation, s ...

  5. HDU - 3247 Resource Archiver(AC自动机+状压dp+bfs)

    题目链接:点击查看 题目大意:给出 n 个目标串和 m 个病毒串,要求构造出一个长度最短的,且包含全部 n 个目标串,但是不能包含任意一个病毒串的01字符串,输出其最短长度 题目分析:比较综合的一道题 ...

  6. HDU - 3341 Lost's revenge(AC自动机+状压dp)

    题目链接:点击查看 题目大意:给出 n 个模式串,最后给出一个匹配串,问如何重新排列匹配串,可以使得匹配串尽可能多的匹配模式串 题目分析:因为是模式串和匹配串的匹配,所以考虑AC自动机,因为数据范围比 ...

  7. P4045-[JSOI2009]密码【AC自动机,状压dp】

    正题 题目链接:https://www.luogu.com.cn/problem/P4045 题目大意 给nnn个字符串,求有多少个长度为lll的字符串包含所有给出的字符串 解题思路 因为nnn很小, ...

  8. hdu 6086 Rikka with String(AC自动机+状压dp)

    题目链接:hdu 6086 Rikka with String 题意: 给你n个只含01的串,和一个长度L,现在让你构造出满足s[i]≠s[|s|−i+1] for all i∈[1,|s|] ,长度 ...

  9. ACM-ICPC 2018 南京赛区网络预赛 J AC Challenge (状压dp)

    题意 给你n道题,在你做第ii{i}道题的时候有p[j]p[j]{p[j]}个前置条件,当这些前置条件都满足的时候,我们可以得到a[j]∗t+b[j]a[j]∗t+b[j]a[j] * t + b[j ...

最新文章

  1. map获取数字与int比较
  2. html 书架样式css,CSS3 响应式书架布局
  3. 微型计算机基础知识答案,计算机基础知识(答案已填)
  4. iOS开发 tabBarController选中状态
  5. SpringSecruity整合Oauth2 详解(一)
  6. 二级路由dhcp关闭连不上wifi_酒店网络故障:原来还与DHCP服务器有关
  7. mysql dump 导入导出_使用mysqldump导入导出数据
  8. visitor-访问模式
  9. CentOS7 reset脚本,用于初始化新的虚拟机
  10. python每隔30s检查一次_Python的全局解释器锁
  11. 【新手入门篇】新浪微博应用开发之Java入门篇
  12. 单片机多大的ram才可以带动tft lcd_【单片机自学】7.液晶实验
  13. docker compose dns 缓存_Docker深入浅出 | Docker Compose多容器实战
  14. [Python+Anaconda] 查看Python、Anaconda下python、CUDA、函数库的版本
  15. AttributeError: ‘_IncompatibleKeys‘ object has no attribute ‘cuda‘
  16. dom影像图形成数字地形图_数字正射影像图DOM
  17. 浏览器历史记录的模式
  18. 非线性规划求解_突破 | 杉数求解器COPT首发求解内点法
  19. 预约订座APP系统(基于uni-app框架)毕业设计毕业论文开题报告参考(3)系统后台管理功能
  20. 【花雕动手做】有趣好玩的音乐可视化系列小项目(19)--通体光纤灯

热门文章

  1. 【开发一个简单的音乐播放器+服务端】【一】
  2. 黑马点评Redis实战(短信登录;商户查询缓存)
  3. Hyperview二次开发:模态阵型的自动排列、输出GIF、输出PPT等
  4. PI Planning
  5. 基于Open vSwitch的传统限速和SDN限速--实验
  6. Ae试水~(待填坑)
  7. ThinkPHP5.0+PHPMailer 实现qq邮箱验证码
  8. Google秘密入口
  9. VLOG的文字遮罩(利用文字显示内部)
  10. 浙江大学机器学习(胡浩基)课程学习笔记一:概述与支持向量机