HDU 2825 AC自动机+DP
题意:一个密码,长度为 n,然后有m个magic words,这个密码至少由k个magic words组成。
问这个密码可能出现的总数。
思路:首先构造AC自动机,由于m很小,才10 ,我们可以使用二进制来表示每个magic words的使用情况。
对于dp[i][j][k],表示长度为i 时,匹配到j这个节点,当前选取的magic words是k 状态时的最大数量。
- #include <set>
- #include <map>
- #include <stack>
- #include <cmath>
- #include <queue>
- #include <cstdio>
- #include <string>
- #include <vector>
- #include <iomanip>
- #include <cstring>
- #include <iostream>
- #include <algorithm>
- #define Max 2505
- #define FI first
- #define SE second
- #define ll long long
- #define PI acos(-1.0)
- #define inf 0x3fffffff
- #define LL(x) ( x << 1 )
- #define bug puts("here")
- #define PII pair<int,int>
- #define RR(x) ( x << 1 | 1 )
- #define mp(a,b) make_pair(a,b)
- #define mem(a,b) memset(a,b,sizeof(a))
- #define REP(i,s,t) for( int i = ( s ) ; i <= ( t ) ; ++ i )
- using namespace std;
- #define MOD 20090717
- #define N 1111111
- int n , m , k ;
- int cnt ;
- struct AC_AUTO {
- int next[26] ;
- int fail ;
- int st ;
- void init() {
- mem(next ,0) ;
- fail = -1 ;
- st = 0 ;
- }
- } a[500000];
- int vis[111111] ;
- void show(int now) {
- vis[now] = 1 ;
- cout << now << " " << a[now].fail << endl;
- for (int i = 0 ; i < 26 ; i ++ ) {
- if(a[now].next[i] != 0 && !vis[a[now].next[i]]) {
- show(a[now].next[i]) ;
- }
- }
- }
- void insert(char *s,int k) {
- int p = 0 ;
- for(int i = 0 ; s[i] ; i ++) {
- int t = s[i] - 'a' ;
- if(a[p].next[t] == 0) {
- a[cnt].init() ;
- a[p].next[t] = cnt ++ ;
- }
- p = a[p].next[t] ;
- }
- a[p].st |= (1 << k) ;
- }
- int q[111111] ;
- void ac_bfs() {
- int i,head = 0,tail = 0;
- q[tail ++]=0;
- while(head < tail) {
- int front = q[head ++];
- for(i = 0; i < 26 ; i ++) {
- if(a[front].next[i] == 0) {///
- if(front == 0)a[front].next[i] = 0 ;
- else a[front].next[i] = a[a[front].fail].next[i] ;
- } else {
- int p = a[front].fail ;
- while(p != -1) {
- if(a[p].next[i] != 0) {
- a[a[front].next[i]].fail = a[p].next[i] ;
- a[a[front].next[i]].st |= a[a[p].next[i]].st ;
- break ;
- }
- p = a[p].fail ;
- }
- if(p == -1)a[a[front].next[i]].fail = 0 ;
- q[tail ++] = a[front].next[i] ;
- }
- }
- }
- }
- int dp[26][200][1 << 10] ;
- int solve() {
- for (int i = 0 ; i <= n ; i ++ )
- for (int j = 0 ; j <= cnt ; j ++ )
- for (int x = 0 ; x <= 1 << m ; x ++ )
- dp[i][j][x] = 0 ;
- dp[0][0][0] = 1 ;
- for (int i = 0 ; i < n ; i ++ )//长度为i时
- for (int j = 0 ; j < cnt ; j ++ )//在第j个节点
- for (int x = 0 ; x < 1 << m ; x ++) { //第x个状态
- if(!dp[i][j][x])continue ;
- for (int y = 0 ; y < 26 ; y ++ ) { //字母y
- int newj = a[j].next[y] ;
- int newst = x | a[newj].st ;
- dp[i + 1][newj][newst] = (dp[i][j][x] + dp[i + 1][newj][newst] ) % MOD ;
- }
- }
- int ans = 0 ;
- for (int i = 0 ; i < 1 << m ; i ++ ) {
- int ret = 0 ;
- int d = i ;
- for (; d ; d -= d & (-d) , ret ++) ;
- if(ret < k )continue ;
- for (int j = 0 ; j < cnt ; j ++ ) {
- ans = (ans + dp[n][j][i]) % MOD ;
- }
- }
- return ans ;
- }
- char in[111] ;
- int main() {
- while(cin >> n >> m >> k, (n + m + k)) {
- a[0].init() ;
- cnt = 1 ;
- for (int i = 0 ; i < m ; i ++ ) {
- scanf("%s",in) ;
- insert(in , i) ;
- }
- ac_bfs() ;
- printf("%d\n",solve()) ;
- }
- return 0 ;
- }
HDU 2825 AC自动机+DP的更多相关文章
- hdu 2825 aC自动机+状压dp
Wireless Password Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others ...
- hdu 2296 aC自动机+dp(得到价值最大的字符串)
Ring Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total Submis ...
- hdu 2457(ac自动机+dp)
题意:容易理解... 分析:这是一道比较简单的ac自动机+dp的题了,直接上代码. 代码实现: #include<stdio.h> #include<string.h> #in ...
- Lost's revenge HDU - 3341 AC自动机+DP(需要学会如何优雅的压缩状态)
题意: 给你n个子串和一个母串,让你重排母串最多能得到多少个子串出现在重排后的母串中. 首先第一步肯定是获取母串中每个字母出现的次数,只有A T C G四种. 这个很容易想到一个dp状态dp[i][A ...
- DNA repair HDU - 2457 AC自动机+DP
题意: 给你N个模板串,并且给你一个文本串, 现在问你这个文本串最少需要改变几个字符才能使得它不包含任何模板串. (以上字符只由A,T,G,C构成) 题解: 刚开始做这一题的时候表示很懵逼,好像没有学 ...
- hdu 2825(ac自动机+状态压缩dp)
题意:容易理解... 分析:在做这道题之前我做了hdu 4057,都是同一种类型的题,因为题中给的模式串的个数最多只能为10个,所以我们就很容易想到用状态压缩来做,但是开始的时候我的代码超时了dp时我 ...
- HDU 2425 DNA repair (AC自动机+DP)
DNA repair Time Limit: 5000/2000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total ...
- HDU 3341 Lost's revenge AC自动机+dp
Lost's revenge Time Limit: 15000/5000 MS (Java/Others) Memory Limit: 65535/65535 K (Java/Others)T ...
- HDU 2457 DNA repair(AC自动机+DP)题解
题意:给你几个模式串,问你主串最少改几个字符能够使主串不包含模式串 思路:从昨天中午开始研究,研究到现在终于看懂了.既然是多模匹配,我们是要用到AC自动机的.我们把主串放到AC自动机上跑,并保证不出现 ...
随机推荐
- C++学习之路—继承与派生(二):派生类的构造函数与析构函数
(根据<C++程序设计>(谭浩强)整理,整理者:华科小涛,@http://www.cnblogs.com/hust-ghtao转载请注明) 由于基类的构造函数和析构函数是不能被继承的,所以 ...
- Android 驱动(二) IIC简单介绍
一. I2C简单介绍 I2C(Inter-Integrated Circuit)总线是一种由 Philips 公司开发的两线式串行总线,用于连接微控制器及其外围设备.I2C 总线最基本的长处就是简单性 ...
- [Android学习笔记]Android向下兼
Android向下兼容的思路:使用高版本的API,在运行时判断真实运行平台的API版本,根据不同版本做不同的处理 关键类:Build.class里面定义了API版本相关信息 内部类:VERSION定义 ...
- NIO框架之MINA源码解析(转)
http://blog.csdn.net/column/details/nio-mina-source.html http://blog.csdn.net/chaofanwei/article/det ...
- Hongwei Xi
Hongwei Xi Hongwei Xi Hongwei Xi's Curriculum Vita Hongwei Xi
- hdu1392 Surround the Trees 凸包
第一次做凸包,这道题要特殊考虑下,n=2时的情况,要除以二才行. 我是从最左边的点出发,每次取斜率最大的点,一直到最右边的点. 然后从最左边的点出发,每次取斜率最低的点,一直到最右边的点. #incl ...
- 自己定义android 4.0以上的对话框风格
做个笔记.这里是Dialog的风格,假设是用AlertDialog创建的,不能直接用.在styles.xml的写法: <style name="DialogWindowTitle&qu ...
- Swift - 使用网格(UICollectionView)进行流布局
一.网格UICollectionView最典型的例子是iBooks.其主要属性如下: 1,layout 该属性表示布局方式,有Flow.Custom两种布局方式.默认是Flow流式布局. 2,Acce ...
- struts 2吊牌s:if 、s:iterator注意
疏忽,也没有相应的总结.实际上JSTL标签Struts2标签混淆.导致一些上述问题的细节.今天我给从下一个总结,同 后不要再犯这种错误. 总喜欢在s:if标签里面使用$,导致各种数据读不出来. str ...
- svn跨机备份
#!/bin/sh svn_bak_dir='/svndata/cloudil' svn_server='svn://172.16.40.200:9999' user=adminread pass=a ...