DP(记忆化搜索) + AC自动机 LA 4126 Password Suspects
2016-02-26 20:27
155 查看
题目传送门
题意:训练指南P250
分析:DFS记忆化搜索,范围或者说是图是已知的字串构成的自动机图,那么用 | (1 << i)表示包含第i个字串,如果长度为len,且st == (1 << m) - 1则是可能的。打印与之前相似。
题意:训练指南P250
分析:DFS记忆化搜索,范围或者说是图是已知的字串构成的自动机图,那么用 | (1 << i)表示包含第i个字串,如果长度为len,且st == (1 << m) - 1则是可能的。打印与之前相似。
#include <bits/stdc++.h> using namespace std; typedef long long ll; const int N = 25 + 5; const int NODE = 10 * 10 + 5; const int M = (1 << 10) + 5; const int SIZE = 26; int n, m; char str[12]; struct AC { int ch[NODE][SIZE], val[NODE], fail[NODE], last[NODE], sz; ll dp[NODE] [M]; int out ; void clear(void) { memset (ch[0], 0, sizeof (ch[0])); sz = 1; } int idx(char c) { return c - 'a'; } void insert(char *s, int v) { int u = 0; for (int c, i=0; s[i]; ++i) { c = idx (s[i]); if (!ch[u][c]) { memset (ch[sz], 0, sizeof (ch[sz])); val[sz] = 0; ch[u][c] = sz++; } u = ch[u][c]; } val[u] |= (1 << v); } void build(void) { queue<int> que; fail[0] = 0; for (int c=0; c<SIZE; ++c) { int u = ch[0][c]; if (u) { fail[u] = 0; last[u] = 0; que.push (u); } } while (!que.empty ()) { int r = que.front (); que.pop (); for (int c=0; c<SIZE; ++c) { int &u = ch[r][c]; if (!u) { u = ch[fail[r]][c]; continue; } que.push (u); int v = fail[r]; while (v && !ch[v][c]) v = fail[v]; fail[u] = ch[v][c]; val[u] |= val[fail[u]]; //last[u] = val[fail[u]] ? fail[u] : last[fail[u]]; } } } void print(int now, int len, int st) { if (len == n) { for (int i=0; i<len; ++i) { printf ("%c", out[i] + 'a'); } puts (""); return ; } for (int c=0; c<SIZE; ++c) { if (dp[ch[now][c]][len+1][st|val[ch[now][c]]] > 0) { out[len] = c; print (ch[now][c], len + 1, st | val[ch[now][c]]); } } } ll DP(int now, int len, int st) { ll &ans = dp[now][len][st]; if (ans != -1) return ans; if (len == n) { if (st == (1 << m) - 1) return ans = 1; else return ans = 0; } ans = 0; for (int c=0; c<SIZE; ++c) { ans += DP (ch[now][c], len + 1, st | val[ch[now][c]]); } return ans; } void run(void) { memset (dp, -1, sizeof (dp)); ll ans = DP (0, 0, 0); printf ("%lld suspects\n", ans); if (ans <= 42) { print (0, 0, 0); } } }ac; int main(void) { int cas = 0; while (scanf ("%d%d", &n, &m) == 2) { if (!n && !m) break; ac.clear (); for (int i=0; i<m; ++i) { scanf ("%s", &str); ac.insert (str, i); } ac.build (); printf ("Case %d: ", ++cas); ac.run (); } return 0; }
相关文章推荐
- 怎样创建TWaver 3D的轮廓选中效果
- 文件操作
- ubuntu 12.04 怎么取得超级用户权利
- C语言学习笔记6-数组
- zoj 3229 有源汇有上下界的最大流模板题
- ionic angularJS input 相关指令 以及定时器 的使用
- 链表的实现
- 双向广度优先搜索(介绍)
- zkw复习小计
- exec函数族的使用
- MAC下查看环境变量的值的方法
- 1021. Deepest Root (25)
- Server redirected too many times (20)解决之道
- uva437
- Android的Activity屏幕左右切换动画
- POJ 2420 A Star not a Tree? (计算几何-费马点)
- 如何确定计算机是32位还是64位
- apache 开启伪静态 Rewrite及检测
- 扫描多边形填充算法
- spark运算结果写入hbase及优化