Title Link: Wireless Password
Parsing: A set of M words that counts the number of programs with at least K words in a string of all lengths of N.
AC Automaton + state compression DP.
DP[I][J][K]: String of length I matches to status J and contains the number of possible strings for K magic word.
AC Code:
#include <algorithm> #include <iostream> #include <cstdio> #include <queue> #include < cstring>using namespace Std;const int MOD = 20090717;int N, m, k;int dp[30][110][1<<10];int num[5000];struct Trie {int next[110][26], fail[110], end[110]; int root, L; int NewNode () {for (int i=0; i<26; i++) Next[l][i] =-1; end[l++] = 0; return L-1; } void Init () {L = 0; root = NewNode (); } void Insert (char buf[], int id) {int len = strlen (BUF); int now = root; for (int i=0; i<len; i++) {if (Next[now][buf[i]-' a '] = =-1) next[now][buf[i]-' a '] = NewNode (); now = next[now][buf[i]-' a ']; } End[now] |= (1<<id); Note} void Build () {queue<int> Q; Fail[root] = root; for (int i=0; i<26; i++) {if (next[root][i] = =-1) next[root][i] = root; else{ Fail[next[root][i]] = root; Q.push (Next[root][i]); }} while (! Q.empty ()) {int now = Q.front (); Q.pop (); End[now] |= End[fail[now]; for (int i=0; i<26; i++) {if (next[now][i] = =-1) next[now][i] = Next[fail[now]][i]; else{Fail[next[now][i]] = next[fail[now]][i]; Q.push (Next[now][i]); }}}} int solve () {//memset (DP, 0, sizeof (DP)); Memset initializes the DP array, which is slower than the following for (int i=0; i<=n; i++) for (int j=0; j<l; j + +) for (int p=0; p < (1<<M); p++) Dp[i][j][p] = 0; Dp[0][0][0] = 1; for (int i=0, i<n; i++) for (int j=0; j<l; j + +) for (int p=0; p< (1<<m); p++) if (Dp[i][j][p] > 0) {for (int x=0; x<26; x + +) { int newi = i+1; int newj = next[j][x]; int newp = (p | end[newj]); DP[NEWI][NEWJ][NEWP] + = dp[i][j][p]; DP[NEWI][NEWJ][NEWP]%= MOD; }} int ans = 0; for (int p=0; p< (1<<m); p++) {if (Num[p] < k) Continue; for (int i=0; i<l; i++) ans = (ans + dp[n][i][p])% MOD; } return ans; }};char BUF[20]; Trie Ac;int Main () {//Freopen ("In.txt", "R", stdin); for (int i=0; i< (1<<10); i++) {num[i] = 0; for (int j=0; j<10; J + +) if (I & (1<<J)) Num[i] + +; } while (scanf ("%d%d%d", &n, &m, &k) = = 3) {if (n = = 0 && m = = 0 && k = = 0) break; Ac.init (); for (int i=0; i<m; i++) {scanf ("%s", buf); Ac.insert (buf, i); } ac.build (); printf ("%d\n", Ac.solve ()); } return 0;}
Copyright NOTICE: This article for Bo Master original article, without Bo Master permission not reproduced.
HDU 2825 Wireless Password (AC automaton + state compression DP)