状压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