bzoj 1559 AC自动机 + dp
思路:直接在状态图上跑dp,最后枚举一下42种一下的。。 这个枚举有点恶心。
#include<bits/stdc++.h>
#define LL long long
#define ll long long
#define fi first
#define se second
#define mk make_pair
#define PII pair<int, int>
#define y1 skldjfskldjg
#define y2 skldfjsklejg using namespace std; const int N = + ;
const int M = 1e7 + ;
const int inf = 0x3f3f3f3f;
const LL INF = 0x3f3f3f3f3f3f3f3f;
const int mod = ; int n, m, up, top, id[N], bord[N][N];
string s[], t[];
bool vis[N]; bool cmp(const string &a, const string &b) {
return a.size() > b.size();
}
bool check(const string &a, const string &b) {
for(int i = ; i < a.size(); i++) {
if(a.substr(i, b.size()) == b) return true;
}
return false;
} int cal(const string &a, const string &b) {
int l1 = a.size(), l2 = b.size();
for(int i = min(l1, l2) - ; i >= ; i--) {
if(a.substr(l1 - i, i) == b.substr(, i)) return i;
}
return ;
} struct Ac {
int ch[N][], val[N], f[N], tot, sz, depth[N];
LL dp[][][ << ];
Ac(int sz) {this->sz = sz;}
void init() {tot = ;};
int newNode() {
tot++; f[tot] = ; val[tot] = ;
memset(ch[tot], , sizeof(ch[tot]));
return tot;
}
inline int idx(char c) {return c - 'a';}
void addStr(string &s, int id) {
int u = ;
for(int i = ; i < s.size(); i++) {
int c = idx(s[i]);
if(!ch[u][c]) ch[u][c] = newNode(), depth[ch[u][c]] = depth[u] + ;
u = ch[u][c];
}
val[u] |= << id;
}
void build() {
queue<int> que;
for(int c = ; c < sz; c++) {
int v = ch[][c];
if(!v) ch[][c] = ;
else f[v] = , que.push(v);
}
while(!que.empty()) {
int u = que.front(); que.pop();
val[u] |= val[f[u]];
for(int c = ; c < sz; c++) {
int v = ch[u][c];
if(!v) ch[u][c] = ch[f[u]][c];
else f[v] = ch[f[u]][c], que.push(v);
}
}
} void solve() {
dp[][][] = ;
for(int k = ; k < n; k++) {
for(int u = ; u <= tot; u++) {
for(int c = ; c < sz; c++) {
int v = ch[u][c];
for(int s = ; s <= up; s++) {
dp[k + ][v][s | val[v]] += dp[k][u][s];
}
}
}
} LL ans = ;
for(int u = ; u <= tot; u++)
ans += dp[n][u][up];
cout << ans << '\n'; if(ans <= ) {
memset(vis, true, sizeof(vis));
sort(s, s + m, cmp);
for(int i = ; i < m; i++)
for(int j = i + ; j < m; j++)
if(check(s[i], s[j])) vis[j] = false; for(int i = ; i < m; i++)
if(vis[i]) id[top] = top, t[top++] = s[i]; for(int i = ; i < top; i++)
for(int j = ; j < top; j++)
if(i != j) bord[i][j] = cal(t[i], t[j]); vector<string> vec;
do {
string ret = t[id[]];
for(int i = ; i < top; i++) {
int len = bord[id[i - ]][id[i]];
ret += t[id[i]].substr(len, );
}
if(ret.size() == n) vec.push_back(ret);
} while(next_permutation(id, id + top)); sort(vec.begin(), vec.end());
for(int i = ; i < vec.size(); i++)
cout << vec[i] << '\n';
}
}
} ac(); int main() {
ac.init();
cin >> n >> m;
for(int i = ; i < m; i++) {
cin >> s[i];
ac.addStr(s[i], i);
}
up = ( << m) - ;
ac.build();
ac.solve();
return ;
} /*
*/
bzoj 1559 AC自动机 + dp的更多相关文章
- bzoj 1030 AC自动机+dp
代码: //先把给的单词建AC自动机并且转移fail,然后d[i][j]表示构造的文章到第i位时处在字典树的第j个节点的不包含单词的数量,最后用总的数量26^m //-d[m][0~sz]即可.其中不 ...
- [BZOJ 1559] [JSOI2009] 密码 【AC自动机DP】
题目链接:BZOJ - 1559 题目分析 将给定的串建成AC自动机,然后在AC自动机上状压DP. 转移边就是Father -> Son 或 Now -> Fail. f[i][j][k] ...
- [BZOJ 3530] [Sdoi2014] 数数 【AC自动机+DP】
题目链接:BZOJ - 3530 题目分析 明显是 AC自动机+DP,外加数位统计. WZY 神犇出的良心省选题,然而去年我太弱..比现在还要弱得多.. 其实现在做这道题,我自己也没想出完整解法.. ...
- bzoj 1030 [JSOI2007]文本生成器(AC自动机+DP)
[题目链接] http://www.lydsy.com/JudgeOnline/problem.php?id=1030 [题意] 给n个小串,随机构造一个长为m的大串,一个串合法当且仅当包含一个或多个 ...
- 【BZOJ】4861: [Beijing2017]魔法咒语 AC自动机+DP+矩阵快速幂
[题意]给定n个原串和m个禁忌串,要求用原串集合能拼出的不含禁忌串且长度为L的串的数量.(60%)n,m<=50,L<=100.(40%)原串长度为1或2,L<=10^18. [算法 ...
- POJ1625 Censored!(AC自动机+DP)
题目问长度m不包含一些不文明单词的字符串有多少个. 依然是水水的AC自动机+DP..做完后发现居然和POJ2778是一道题,回过头来看都水水的... dp[i][j]表示长度i(在自动机转移i步)且后 ...
- HDU2296 Ring(AC自动机+DP)
题目是给几个带有价值的单词.而一个字符串的价值是 各单词在它里面出现次数*单词价值 的和,问长度不超过n的最大价值的字符串是什么? 依然是入门的AC自动机+DP题..不一样的是这题要输出具体方案,加个 ...
- HDU2457 DNA repair(AC自动机+DP)
题目一串DNA最少需要修改几个基因使其不包含一些致病DNA片段. 这道题应该是AC自动机+DP的入门题了,有POJ2778基础不难写出来. dp[i][j]表示原DNA前i位(在AC自动机上转移i步) ...
- hdu 4117 GRE Words AC自动机DP
题目:给出n个串,问最多能够选出多少个串,使得前面串是后面串的子串(按照输入顺序) 分析: 其实这题是这题SPOJ 7758. Growing Strings AC自动机DP的进阶版本,主题思想差不多 ...
随机推荐
- git与svn与github与码云的区别
1.git与github(https://www.oschina.net/)的区别 Git(https://git-scm.com/)是一个版本控制工具 github是一个用git做版本控制的项目托管 ...
- 组合框控件 -- CComboBox
组合框控件 -- CComboBox 组合框其实就是把一个编辑框和一个列表框组合到了一起,分为三种:简易(Simple)组合框.下拉式(Dropdown)组合框和下拉列表式(Drop List)组合框 ...
- FreeRTOS ------ 栈、堆、任务栈
1.任务的栈资源(创建任务分配的资源,单位是4字节)来自 configTOTAL_HEAP_SIZE 定义的堆,如果任务栈总量超过 configTOTAL_HEAP_SIZE,任务创建失败: 2.如果 ...
- CentOS 下安装Mplayer播放器(转载)
一.准备工作 需要的安装包及下载地址:1.mplayer源代码包(MPlayer-1.0rc4.tar.bz2)下载:http://www.mplayerhq.hu/MPlayer/releases/ ...
- python读书笔记-《简明python教程》上
1月15日 <简明python教程>上 基本结构: 基础概念+控制流+函数+模块+数据结构+面向对象+I/O+异常+标准库+其他 1.概念 1-0 退出python linux: ...
- svn update解决冲突
(p) postpone 暂时推后处理,我可能要和那个和我冲突的家伙商量一番 (df) diff-full 把所有的修改列出来,比比看 (e) edit 直接编辑冲突的文件 (mc) mine-con ...
- 51Nod 1031 骨牌覆盖 | Fibonacci
Input 输入N(N <= 1000) Output 输出数量 Mod 10^9 + 7 Input示例 3 Output示例 3 思路:对于第x块骨牌的情况,我们用a[x]表示其方法数:其比 ...
- LightOJ 1085 - All Possible Increasing Subsequences 树状数组+离散
http://www.lightoj.com/volume_showproblem.php?problem=1085 题意:求一个序列的递增子序列个数. 思路:找规律可以发现,某个数作为末尾数的种类数 ...
- Markdown 代码块中再内嵌一个行内代码
在 jQuery 1.9 之前(不含1.9):如果传入一个空字符串. null 或 jQuery.parseJSON( jsonString ) ,该函数将返回,而不是抛出一个错误,即使它不是有效的 ...
- linux下进行base64编码解码
1.编码 2.解码