hdu2825Wireless Password(ac+dp)

链接

状压dp+ac

dp[i+1][next[j]][st|tt]表示第i+1长度结点为next[j]状态为st|tt的时候的ans;

dp[i+1][next[j]][st|tt]+=dp[i][j][tt]; st记录当前结点是否为给定单词的结束点

后一维用01状态表示截止到目前结点为止所包含的单词数量。

需要修改ac模板的一个地方,val[u]|=val[fail[u]];

  1 #include <iostream>
2 #include<cstdio>
3 #include<cstring>
4 #include<algorithm>
5 #include<stdlib.h>
6 #include<vector>
7 #include<cmath>
8 #include<queue>
9 #include<set>
10 using namespace std;
11 #define N 115
12 #define LL long long
13 #define INF 0xfffffff
14 const double eps = 1e-8;
15 const double pi = acos(-1.0);
16 const double inf = ~0u>>2;
17 const int child_num = 26;
18 const int mod = 20090717;
19 class AC
20 {
21 private:
22 int ch[N][child_num];
23 int fail[N];
24 int Q[N];
25 int val[N];
26 int sz;
27 int id[128];
28 int dp[30][N][1<<10];
29 public:
30 void init()
31 {
32 fail[0] =0;
33 for(int i = 0 ;i < child_num ; i++)
34 id[i+‘a‘] = i;
35 }
36 void reset()
37 {
38 memset(val,0,sizeof(val));
39 memset(ch[0],0,sizeof(ch[0]));
40 //memset(fail,0,sizeof(fail));
41 sz = 1;
42 }
43 void insert(char *a,int key)
44 {
45 int p = 0;
46 for(; *a ; a++)
47 {
48 int d = id[*a];
49 if(ch[p][d]==0)
50 {
51 memset(ch[sz],0,sizeof(ch[sz]));
52 ch[p][d] = sz++;
53 }
54 p = ch[p][d];
55 }
56 val[p] = (1<<key);
57 }
58 void construct()
59 {
60 int i,head=0,tail = 0;
61 for(i = 0 ;i < child_num ; i++)
62 {
63 if(ch[0][i])
64 {
65 fail[ch[0][i]] = 0;
66 Q[tail++] = ch[0][i];
67 }
68 }
69 while(head!=tail)
70 {
71 int u = Q[head++];
72 val[u]|=val[fail[u]];
73 for(i = 0 ;i < child_num ;i++)
74 {
75 if(ch[u][i])
76 {
77 fail[ch[u][i]] = ch[fail[u]][i];
78 Q[tail++] = ch[u][i];
79 }
80 else ch[u][i] = ch[fail[u]][i];
81 }
82 }
83 }
84 void work(int n,int k,int m)
85 {
86 int i,j,g,o;
87 for(i = 0 ; i <= n ;i++)
88 for(j = 0 ; j <= sz ; j++)
89 for(g = 0 ;g <=(1<<m) ; g++)
90 dp[i][j][g] = 0;
91 dp[0][0][0] = 1;
92 for(i = 0; i < n ;i++)
93 for(j = 0; j < sz ; j++)
94 {
95 for(int e =0 ; e < (1<<m) ; e++)
96 {
97 if(!dp[i][j][e]) continue;
98 for(g = 0 ;g < child_num ; g++)
99 {
100 o = 0;
101 if(val[ch[j][g]])
102 {
103 o = val[ch[j][g]];
104 }
105 dp[i+1][ch[j][g]][e|o]=(dp[i+1][ch[j][g]][e|o]+dp[i][j][e])%mod;
106 }
107 }
108 }
109 int ans = 0;
110 for(i = 0 ; i < sz;i ++)
111 {
112 for(j = 0 ;j < (1<<m) ; j++)
113 {
114 if(!dp[n][i][j]) continue;
115 int o =0 ;
116 for(g = 0 ;g < m ; g++)
117 if(j&(1<<g)) o++;
118 if(o>=k)
119 ans = (ans+dp[n][i][j])%mod;
120 }
121 }
122 printf("%d\n",ans);
123 }
124 }ac;
125 char vir[15];
126 int main()
127 {
128 int n,m,k,i;
129 ac.init();
130 while(scanf("%d%d%d",&n,&m,&k)!=EOF)
131 {
132 if(!n&&!m&&!k) break;
133 ac.reset();
134 for(i = 1; i <= m; i++)
135 {
136 scanf("%s",vir);
137 ac.insert(vir,i-1);
138 }
139 ac.construct();
140 ac.work(n,k,m);
141 }
142 return 0;
143 }

hdu2825Wireless Password(ac+dp),布布扣,bubuko.com

时间: 2024-11-04 19:32:27

hdu2825Wireless Password(ac+dp)的相关文章

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自动机&amp;dp)

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

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

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

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 <

HDU 2825 Wireless Password (AC自动机,DP)

http://acm.hdu.edu.cn/showproblem.php?pid=2825 Wireless Password Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 4560    Accepted Submission(s): 1381 Problem Description Liyuan lives in a old 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 Wireless Password AC自动机+dp

训练赛第二场的I题,上完体育课回来就把这题过了,今天训练赛rank1了,还把大大队虐了,而且我还过了这道题 (虽然我也就过了这道题...),第一次在比赛中手写AC自动机还带dp的,心情大好. 给一个字符串集合,求包含该集合超过K个字符的,长度为L的字符串的个数. 显然是在AC自动机上跑dp,设dp[u][L][k]表示当前在结点u,还要走L步,当前状态为k的个数.一开始第三维表示的是包含k个字符串,但是题目要求不含重复的,那就只能状压了.转移为dp[u][L][k]+=dp[v][L-1][nk

HDU 2825 Wireless Password(自动机+DP)

Problem Description Liyuan lives in a old apartment. One day, he suddenly found that there was a wireless network in the building. Liyuan did not know the password of the network, but he got some important information from his neighbor. He knew the p

AC自动机

AC自动机 直接学AC自动机比较难理解,强烈建议先学完KMP和字典树并进行一定的练习后,对于失配指针和字典树构造有一定理解后再来学AC自动机的内容.有关AC自动机的详细介绍可见刘汝佳的<算法竞赛入门经典训练指南>P214. 给你一个字典(包含n个不重复的单词),然后给你一串连续的字符串文本(长为len),问你该文本里面的哪些位置正好出现了字典中的某一个或某几个单词?输出这些位置以及出现的单词. 这个问题可以用n个单词的n次KMP算法来做(效率为O(n*len*单词平均长度)),也可以用1个字典