【AC自动机】 HDOJ 2825 Wireless Password
来源:互联网 发布:淘宝双十一h5页面 编辑:程序博客网 时间:2024/05/16 04:42
AC自动机+状态压缩DP。用dp[i][j][k]表示走i步,到达AC自动机中的j节点,含有的字符串k种类(二进制状态压缩),所有的方案数。
#include <iostream>#include <sstream>#include <algorithm>#include <vector>#include <queue>#include <stack>#include <map>#include <set>#include <bitset>#include <cstdio>#include <cstring>#include <cstdlib>#include <cmath>#include <climits>#define maxn 105#define eps 1e-6#define mod 20090717#define INF 99999999#define lowbit(x) (x&(-x))//#define lson o<<1, L, mid//#define rson o<<1 | 1, mid+1, Rtypedef long long LL;typedef unsigned long long ULL;using namespace std;struct node{ int next[maxn][26]; int fail[maxn]; int end[maxn]; char s[maxn]; queue<int> q; int top, now, root; int newnode(void) { end[top] = 0; fail[top] = -1; for(int i = 0; i < 26; i++) next[top][i] = -1; return top++; } void init(void) { top = 0; root = newnode(); } void insert(int x) { int i, len = strlen(s), k; now = root; for(i = 0; i < len; i++) { k = s[i] - 'a'; if(next[now][k] == -1) next[now][k] = newnode(); now = next[now][k]; } end[now] = x; } void build(void) { int i; fail[root] = root; now = root; for(i = 0; i < 26; i++) if(next[now][i] == -1) next[now][i] = root; else { fail[next[now][i]] = root; q.push(next[now][i]); } while(!q.empty()) { now = q.front(); q.pop();end[now] |= end[fail[now]]; for(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]); } } }}trie;int dp[30][105][1100];int is[1100];int n, m, kk;void read(void){ int i, tmp = 1; trie.init(); for(i = 1; i <= m; i++) { scanf("%s", trie.s); trie.insert(tmp); tmp<<=1; } trie.build();}void init(void){ memset(dp, 0, sizeof dp);}void work(void){ int o = 0, i, j, k, ans, tmp, res, cnt, p; for(i = 0; i < m; i++) o<<=1, o+=1; dp[0][0][0] = 1; for(i = 0; i <= n; i++) for(j = 0; j < trie.top; j++) for(k = 0; k <= o; k++) { if(dp[i][j][k] == 0) continue; for(p = 0; p < 26; p++) dp[i+1][trie.next[j][p]][k|trie.end[trie.next[j][p]]] = (dp[i+1][trie.next[j][p]][k|trie.end[trie.next[j][p]]] + dp[i][j][k])%mod; } ans = 0; cnt = 0; for(i = 0; i <= o; i++) { tmp = i; res = 0; while(tmp) res+=tmp&1, tmp>>=1; if(res >= kk) is[cnt++] = i; } for(i = 0; i < trie.top; i++) for(j = 0; j < cnt; j++) ans = (ans + dp[n][i][is[j]])%mod; printf("%d\n", ans);}int main(void){ while(scanf("%d%d%d", &n, &m, &kk), n!=0 || m!=0 || kk!=0) { init(); read(); work(); } return 0;}
后来对程序优化了一下,跑的更快了。
#include <iostream>#include <sstream>#include <algorithm>#include <vector>#include <queue>#include <stack>#include <map>#include <set>#include <bitset>#include <cstdio>#include <cstring>#include <cstdlib>#include <cmath>#include <climits>#define maxn 105#define eps 1e-6#define mod 20090717#define INF 99999999#define lowbit(x) (x&(-x))//#define lson o<<1, L, mid//#define rson o<<1 | 1, mid+1, Rtypedef long long LL;typedef unsigned long long ULL;using namespace std;int next[maxn][26];int fail[maxn];int end[maxn];char s[maxn];int dp[30][105][1100];int hash[1100];int n, m, kk;queue<int> q;int top, now, root;int newnode(void){ end[top] = 0; fail[top] = -1; for(int i = 0; i < 26; i++) next[top][i] = -1; return top++;}void init(void){ top = 0; root = newnode();}void insert(int x){ int i, len = strlen(s), k; now = root; for(i = 0; i < len; i++) { k = s[i] - 'a'; if(next[now][k] == -1) next[now][k] = newnode(); now = next[now][k]; } end[now] = x;}void build(void){ int i; fail[root] = root; now = root; for(i = 0; i < 26; i++) if(next[now][i] == -1) next[now][i] = root; else { fail[next[now][i]] = root; q.push(next[now][i]); } while(!q.empty()) { now = q.front(); q.pop(); end[now] |= end[fail[now]]; for(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]); } }}void read(void){ int i, tmp = 1; for(i = 1; i <= m; i++) { scanf("%s", s); insert(tmp); tmp<<=1; } build();}void work(void){ int o = 0, i, j, k, ans, p; for(i = 0; i < m; i++) o<<=1, o+=1; for(i = 0; i <= n; i++) for(j = 0; j < top; j++) for(k = 0; k <= o; k++) dp[i][j][k] =0; dp[0][0][0] = 1; for(i = 0; i < n; i++) for(j = 0; j < top; j++) for(k = 0; k <= o; k++) { if(dp[i][j][k] == 0) continue; for(p = 0; p < 26; p++) dp[i+1][next[j][p]][k|end[next[j][p]]] = (dp[i+1][next[j][p]][k|end[next[j][p]]] + dp[i][j][k])%mod; } ans = 0; for(i = 0; i <= o; i++) if(hash[i] >= kk) for(j = 0; j < top; j++) ans = (ans + dp[n][j][i])%mod; printf("%d\n", ans);}int main(void){ int i, j; for(i = 0; i < (1<<10); i++) { hash[i] = 0; for(j = 0; j < 10; j++) if(i & (1<<j)) hash[i]++; } while(scanf("%d%d%d", &n, &m, &kk), n!=0 || m!=0 || kk!=0) { init(); read(); work(); } return 0;}
0 0
- 【AC自动机】 HDOJ 2825 Wireless Password
- hdoj 2825 Wireless Password 【AC自动机 + 状压dp】
- hdu 2825 Wireless Password 【ac自动机+dp】
- HDU 2825 Wireless Password【AC自动机+DP】
- hdu 2825 Wireless Password(ac自动机&dp)
- 【HDU】2825 Wireless Password AC自动机+DP
- HDU - 2825 Wireless Password(AC自动机+DP)
- HDU 2825 Wireless Password (AC自动机,DP)
- HDU2825 Wireless Password AC自动机
- HDU2825 Wireless Password【AC自动机】
- [HDU2825]Wireless Password-AC自动机
- hdu 2825 Wireless Password AC自动机+状态压缩DP
- HDU 2825 Wireless Password(AC自动机+状压DP)
- HDU 2825 Wireless Password && AC自动机+状压DP
- hdu 2825 Wireless Password(AC自动机+状压DP)
- HDU 2825 Wireless Password(AC自动机+状态压缩DP)
- [AC自动机+状压dp] hdu 2825 Wireless Password
- hdu 2825 Wireless Password(AC自动机+状压DP)
- JavaWeb学习笔记 第三记
- android 学习题6-比较好
- window和linux下,设置socket为阻塞模式
- 通过shell进行数学运算
- LeetCode: Distinct Subsequences
- 【AC自动机】 HDOJ 2825 Wireless Password
- UVA 10620 - A Flea on a Chessboard(鸽笼原理)
- android 复习7比较好
- MYSQL导入数据到TXT
- 会见teambition齐俊元
- 选择类排序——简单选择排序
- android复习7比较好
- html自我学习总结(不全面)
- 转:闭包的概念、形式与应用