HDU2825 Wireless Password(AC自动机+状压DP)

题目问长度n至少包含k个咒语的字符串有多少个。也是比较入门的题。。

  • dp[i][j][S]表示长度i(在自动机上转移k步)且后缀状态为自动机上第j个结点且当前包含咒语集合为S的方案数
  • dp[0][0][0]=1
  • 还是用我为人人转移,AC自动机上的结点要多一个域表示这个结点所代表咒语前缀包含的咒语集合。
 1 #include<cstdio>
 2 #include<cstring>
 3 #include<queue>
 4 using namespace std;
 5 int tn,ch[111][26],fail[111],flag[111];
 6 void insert(char *s,int k){
 7     int x=0;
 8     for(int i=0; s[i]; ++i){
 9         int y=s[i]-‘a‘;
10         if(ch[x][y]==0) ch[x][y]=++tn;
11         x=ch[x][y];
12     }
13     flag[x]|=1<<k;
14 }
15 void init(){
16     memset(fail,0,sizeof(fail));
17     queue<int> que;
18     for(int i=0; i<26; ++i){
19         if(ch[0][i]) que.push(ch[0][i]);
20     }
21     while(!que.empty()){
22         int x=que.front(); que.pop();
23         for(int i=0; i<26; ++i){
24             if(ch[x][i]) que.push(ch[x][i]),fail[ch[x][i]]=ch[fail[x]][i];
25             else ch[x][i]=ch[fail[x]][i];
26             flag[ch[x][i]]|=flag[ch[fail[x]][i]];
27         }
28     }
29 }
30 int getCnt(int s){
31     int res=0;
32     for(int i=0; i<10; ++i){
33         if((s>>i)&1) ++res;
34     }
35     return res;
36 }
37 int d[26][111][1<<10];
38 int main(){
39     char str[11];
40     int n,m,k;
41     while(~scanf("%d%d%d",&n,&m,&k) && (n||m||k)){
42         tn=0;
43         memset(ch,0,sizeof(ch));
44         memset(flag,0,sizeof(flag));
45         for(int i=0; i<m; ++i){
46             scanf("%s",str);
47             insert(str,i);
48         }
49         init();
50         memset(d,0,sizeof(d));
51         d[0][0][0]=1;
52         for(int i=0; i<n; ++i){
53             for(int j=0; j<=tn; ++j){
54                 for(int k=0; k<(1<<m); ++k){
55                     if(d[i][j][k]==0) continue;
56                     for(int y=0; y<26; ++y){
57                         d[i+1][ch[j][y]][k|flag[ch[j][y]]]+=d[i][j][k];
58                         d[i+1][ch[j][y]][k|flag[ch[j][y]]]%=20090717;
59                     }
60                 }
61             }
62         }
63         int res=0;
64         for(int i=0; i<=tn; ++i){
65             for(int j=0; j<(1<<m); ++j){
66                 if(getCnt(j)<k) continue;
67                 res+=d[n][i][j];
68                 res%=20090717;
69             }
70         }
71         printf("%d\n",res);
72     }
73     return 0;
74 }
时间: 2024-10-05 16:13:33

HDU2825 Wireless Password(AC自动机+状压DP)的相关文章

hdu 2825 Wireless Password(AC自动机+状压DP)

题目链接:hdu 2825 Wireless Password 题目大意:N,M,K,M个字符串作为关键码集合,现在要求长度为N,包含K个以上的关键码的字符串有多少个. 解题思路:AC自动机+dp,滚动数组,因为关键码个数不会超过10个,所以我们用二进制数表示匹配的状态.dp[i][j][k] 表示到第i个位置,j节点,匹配k个字符串. #include <cstdio> #include <cstring> #include <queue> #include <

hdu2825---Wireless Password(AC自动机+状压dp)

Wireless Password Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 4688 Accepted Submission(s): 1433 Problem Description Liyuan lives in a old apartment. One day, he suddenly found that there was a

hdu_2825_Wireless Password(AC自动机+状压DP)

题目链接:hdu_2825_Wireless Password 题意: 给你m个串,问长度为n至少含k个串的字符串有多少个 题解: 设dp[i][j][k]表示考虑到长度为i,第j个自动机的节点,含有k这个压缩状态的方案数,然后DP下去就行了 1 #include<bits/stdc++.h> 2 #define F(i,a,b) for(int i=a;i<=b;i++) 3 using namespace std; 4 5 const int mod=20090717; 6 cons

hdu 2825 aC自动机+状压dp

Wireless Password Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 5640    Accepted Submission(s): 1785 Problem Description Liyuan lives in a old apartment. One day, he suddenly found that there

poj 1699 Best Sequence(AC自动机+状压DP)

题目链接:poj 1699 Best Sequence 题目大意:给定N个DNA序列,问说最少多长的字符串包含所有序列. 解题思路:AC自动机+状压DP,先对字符串构造AC自动机,然后在dp[s][i]表示匹配了s,移动到节点i时候的最短步数. #include <cstdio> #include <cstring> #include <queue> #include <vector> #include <iostream> #include &

【HDU3341】 Lost&#39;s revenge (AC自动机+状压DP)

Lost's revenge Time Limit: 5000MS Memory Limit: 65535KB 64bit IO Format: %I64d & %I64u Description Lost and AekdyCoin are friends. They always play "number game"(A boring game based on number theory) together. We all know that AekdyCoin is t

HDU 3341 Lost&#39;s revenge(AC自动机+状压DP)

Lost's revenge Time Limit: 15000/5000 MS (Java/Others)    Memory Limit: 65535/65535 K (Java/Others)Total Submission(s): 4548    Accepted Submission(s): 1274 Problem Description Lost and AekdyCoin are friends. They always play "number game"(A bor

[AC自动机+状压dp] hdu 2825 Wireless Password

题意: 给n,m,k ,再给出m个单词 问长度为n的字符串,至少在m个单词中含有k个的组成方案有多少种. 思路: 由于m最大是10,所以可以采取状压的思想 首先建立trie图,在每个单词的结束节点标记一个mark=(1<<id),id为单词的编号 然后需要注意的,对于每个节点,应该顺着fail指针遍历一遍, 把所有的mark取一个并集. 因为就是如果单词出现包含的话,比如 she和he 我拿了she,其实等于两个都拿了. dp[i][j][k]  i步在节点j状态k的方案数 然后就是一个四重循

[AC自动机+状压dp] hdu 4534 郑厂长系列故事——新闻净化

题意:中文的题目,意思就是说有很多串,每个串都有权值,权值为999的串必须出现,-999的串必须不出现.权值在-999~999之间. 然后必须出现的串不超过8个.然后给一个全为小写目标串,问最少需要删除多少个字母才能够保证必须出现的串都出现,次数一样保证权值最大.输出次数和权值. 然后根据样例,那些必须出现的串,其实权值是0. 思路: 很明显一开始建自动机构成trie图,但是需要注意的就是mark和sum的更新.个人是把所有中间的节点的sum全部赋值成了-inf. 接着只有8个必须出现的串,所以

POJ1699 Best Sequence(AC自动机+状压DP)

题目,包含所有的给定的n个DNA片段的序列的最短长度. 裸的AC自动机上的DP题. dp[S][u]表示已经包含的DNA片段集合为S,且当前后缀状态是自动机第u个结点的最短长度 dp[0][0]=0 我为人人+队列轻松转移.. 1 #include<cstdio> 2 #include<cstring> 3 #include<queue> 4 #include<algorithm> 5 using namespace std; 6 #define INF (