[luogu]P2167 [SDOI2009]Bill的挑战

原题链接:P2167 [SDOI2009]Bill的挑战

题意

有$n(le 15)$个等长字符串,由小写字母和'?'构成,'?'任意匹配。

求有多少个字符串与刚好$k$个匹配。

分析

做了好久然后发现没有这么难,想复杂了。

原来想法是$f[i][j][S]$表示匹配到前$i$个字母,第$i$个字母为$j$,最大匹配集合为$S$的方案数。

然后发现第二个条件没有用。删掉就行了。

状态转移方程?

对于每个$S$,枚举下一个字母,然后与$S$中的串进行匹配,寻找交集,直接加上去就行了。

代码

 1 #include <bits/stdc++.h>
 2 #define Mid ((l + r) >> 1)
 3 #define lson (rt << 1)
 4 #define rson (rt << 1 | 1)
 5 using namespace std;
 6 const int mod = 1e6 + 3;
 7 int read(){
 8     char c; int num, f = 1;
 9     while(c = getchar(),!isdigit(c)) if(c == '-') f = -1; num = c - '0';
10     while(c = getchar(), isdigit(c)) num = num * 10 + c - '0';;
11     return f * num;
12 }
13 int n, m, k, f[59][1 << 15], len[59], maxn;
14 int a[15][59], pcnt[1 << 15];
15 char c[59];
16 void up(int &a, int b){
17     a = (a + b);
18     if(a > mod) a -= mod;
19 }
20 void work(){
21     memset(f, 0, sizeof(f));
22     n = read(); k = read();
23     for(int i = 0; i < n; i++){
24         scanf("%s", c + 1);
25         m = strlen(c + 1);
26         for(int j = 1; j <= m; j++){
27             if(c[j] == '?') a[i][j] = 26;
28             else a[i][j] = c[j] - 'a';
29         }
30     }
31     for(int i = 0; i < 1 << n; i++)
32         pcnt[i] = pcnt[i >> 1] + (i & 1);
33     f[0][(1 << n) - 1] = 1;
34     for(int i = 0; i < m; i++){
35         for(int s = 0; s < 1 << n; s++)if(f[i][s]){
36             for(int j = 0; j < 26; j++){
37                 int mask = 0;
38                 for(int p = 0; p < n; p++) if(s & 1 << p)
39                     if(a[p][i + 1] == 26 || a[p][i + 1] == j)
40                         mask |= 1 << p;
41                 up(f[i + 1][mask], f[i][s]);
42             }
43         }
44     }
45     int ans = 0;
46     for(int i = 0; i < 1 << n; i++){
47         if(pcnt[i] == k)
48             up(ans, f[m][i]);
49         
50     }
51     printf("%d
", ans);
52 }
53 main()
54 {
55     int Case = read();
56     while(Case--) work();
57     return 0;
58 }
59 /*
60 f[i][s]表示匹配到前i位,匹配的状态为s的方案数
61 
62 */
View Code
原文地址:https://www.cnblogs.com/onglublog/p/14186928.html