题意:给出n个资源,m个病毒,将资源串拼接成一个串,必须包含所有的资源串,可以重叠,但是不能包含病毒,问最小的长度为多少

题解:所有串建AC自动机。对以资源串结尾的结点跑bfs,求出到其他资源串结尾的最小距离。当前结点的fail结点不能入队列,因为当前结点读下一个字符可能会遇到禁止字符串,而fail结点读相同字符可能没有遇到禁止字符串...所以每次直接将nex的可行结点入队列。(fail结点不入队列,直接设为与当前结点距离为0应该也是可行的,然而WA了)很多时候我都开始质疑数据问题了...

如果当前字符串本身包含另一个资源串,那距离不应当是0吗?有一种解释是dp的时候经过 | 操作就可以了。

 #include <bits/stdc++.h>
#include <cstdio>
#include <iostream>
#include <algorithm>
#define ll long long
#define lson l, m, rt<<1
#define rson m+1, r, rt<<1|1
#define st first
#define nd second
#define mp make_pair
#define pii pair<int, int>
#define gg puts("gg");
#define local
//#define out1
using namespace std;
const int N = 6e4+;
const int inf = 0x3f3f3f3f;
int id(char c){
return c == '';
}
struct Tire{
int nex[N][], fail[N],end[N];
int root, L;
int node[], tot;
int newnode(){
nex[L][] = nex[L][] = -;
end[L] = ;
return L++;
}
void init(){
L = tot = ;
root = newnode();
}
void insert(char* s, int tag){
int now = root;
for(int i = ; s[i]; i++){
int p = id(s[i]);
if(nex[now][p] == -)
nex[now][p] = newnode();
now = nex[now][p];
}
if(tag >= )
end[now] |= <<tag;
else end[now] = -;
}
void build(){
queue<int> Q;
fail[root] = root;
for(int i = ; i < ; i++){
int& u = nex[root][i];
if(u == -)
u = root;
else{
fail[u] = root;
Q.push(u);
}
}
while(!Q.empty()){
int now = Q.front();
Q.pop();
for(int i = ; i < ; i++){
int& u = nex[now][i];
if(u == -)
u = nex[ fail[now] ][i];
else{
fail[u] = nex[ fail[now] ][i];
end[u] |= end[ fail[u] ];
Q.push(u);
}
}
}
}
};
Tire ac;
char s[N];
void gmin(int& a, int b){
if(a > b) a = b;
}
int dis[N], ve[N], tot;
int w[][]; void bfs(int node, int i){
memset(dis, 0x3f, sizeof(dis));
queue<int> Q;
Q.push(node); dis[node] = ;
int s = ; #ifdef out1
int j = node;
while(ac.fail[j] != ac.root){
j = ac.fail[j];
dis[j] = ;
}
dis[j] = ;
#endif while(!Q.empty()){
int sz = Q.size();
s++;
while(sz--){
int f = Q.front(); Q.pop();
for(int j = ; j < ; j++){
int to = ac.nex[f][j];
if(dis[to] < inf||ac.end[to] < ) continue ;
Q.push(to);
dis[to] = s; #ifdef out1
while(ac.fail[to] != ac.root&&dis[ac.fail[to]] == inf){
to = ac.fail[to];
dis[to] = s;
}
#endif
}
}
}
for(int j = ; j < tot; j++)
w[i][j] = dis[ ve[j] ];
}
int dp[][<<];
int main(){
#ifdef locl
freopen("in", "r", stdin);
#ifdef out1
freopen("out1", "w", stdout);
#else
freopen("out2", "w", stdout);
#endif // out1
#endif // locl
int n, m, t, ca = ;
while(~scanf("%d%d", &n, &m), n+m){
ac.init(); memset(w, 0x3f, sizeof(w));
for(int i = ; i < n; i++){
w[i][i] = ;
scanf("%s", s);
ac.insert(s, i);
}
for(int i = ; i < m; i++){
scanf("%s", s);
ac.insert(s, -);
}
ac.build(); tot = ;
for(int i = ; i < ac.L; i++)
if(!i||ac.end[i] > ) ve[tot++] = i;
memset(w, 0x3f, sizeof(w));
for(int i = ; i < tot; i++)
bfs(ve[i], i);
// for(int i = 0; i < tot; i++){
// for(int j = 0; j < tot; j++)
// printf("%10d ", w[i][j]);
// puts("");
// } memset(dp, 0x3f, sizeof(dp));
for(int i = ; i < tot; i++)
dp[i][ ac.end[ve[i]] ] = w[][i];
for(int i = ; i < (<<n); i++){
for(int j = ; j < tot; j++){
if( dp[j][i] < 0x3f3f3f3f ) for(int k = ; k < tot; k++)
if(j != k&&w[j][k] < 0x3f3f3f3f)
gmin(dp[k][i|ac.end[ve[k]]], dp[j][i]+w[j][k]);
}
} // for(int i = 0; i < n; i++)
// for(int j = 0; j < (1<<n); j++)
// printf("%d %d: %d\n", i, j, dp[i][j]); int ans = inf;
for(int i = ; i < tot; i++)
ans = min(ans, dp[i][ (<<n)- ]);
printf("%d\n", ans);
}
return ;
}
/*
2 2
1110
0111
101
1001 3 3
0001000
00100
010
11
111
1111
*/

HDU3247 AC自动机+dp的更多相关文章

  1. POJ1625 Censored!(AC自动机+DP)

    题目问长度m不包含一些不文明单词的字符串有多少个. 依然是水水的AC自动机+DP..做完后发现居然和POJ2778是一道题,回过头来看都水水的... dp[i][j]表示长度i(在自动机转移i步)且后 ...

  2. HDU2296 Ring(AC自动机+DP)

    题目是给几个带有价值的单词.而一个字符串的价值是 各单词在它里面出现次数*单词价值 的和,问长度不超过n的最大价值的字符串是什么? 依然是入门的AC自动机+DP题..不一样的是这题要输出具体方案,加个 ...

  3. HDU2457 DNA repair(AC自动机+DP)

    题目一串DNA最少需要修改几个基因使其不包含一些致病DNA片段. 这道题应该是AC自动机+DP的入门题了,有POJ2778基础不难写出来. dp[i][j]表示原DNA前i位(在AC自动机上转移i步) ...

  4. hdu 4117 GRE Words AC自动机DP

    题目:给出n个串,问最多能够选出多少个串,使得前面串是后面串的子串(按照输入顺序) 分析: 其实这题是这题SPOJ 7758. Growing Strings AC自动机DP的进阶版本,主题思想差不多 ...

  5. hdu 2457(ac自动机+dp)

    题意:容易理解... 分析:这是一道比较简单的ac自动机+dp的题了,直接上代码. 代码实现: #include<stdio.h> #include<string.h> #in ...

  6. HDU 2425 DNA repair (AC自动机+DP)

    DNA repair Time Limit: 5000/2000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total ...

  7. HDU2296——Ring(AC自动机+DP)

    题意:输入N代表字符串长度,输入M代表喜欢的词语的个数,接下来是M个词语,然后是M个词语每个的价值.求字符串的最大价值.每个单词的价值就是单价*出现次数.单词可以重叠.如果不止一个答案,选择字典序最小 ...

  8. tyvj P1519 博彩游戏(AC自动机+DP滚动数组)

    P1519 博彩游戏 背景 Bob最近迷上了一个博彩游戏…… 描述 这个游戏的规则是这样的:每花一块钱可以得到一个随机数R,花上N块钱就可以得到一个随机序列:有M个序列,如果某个序列是产生的随机序列的 ...

  9. bzoj 1030 [JSOI2007]文本生成器(AC自动机+DP)

    [题目链接] http://www.lydsy.com/JudgeOnline/problem.php?id=1030 [题意] 给n个小串,随机构造一个长为m的大串,一个串合法当且仅当包含一个或多个 ...

随机推荐

  1. yii2框架安装

    注意:先把php.ini里面的php_openssl.dll扩展打开 1.下载yii2框架的文件包yii-advanced-app-2.0.7 2.打开路径为advanced下面的init.bat   ...

  2. springMVC配置freemarker 二(问题讨论篇)

    上面一篇我已经说明了如何去配置freemarker,这里我就谈谈遇到的问题吧. 首先, 为什么要删除上面之前的.你要使用freemarkerviewresolver和上面的冲突了,因此要注释掉上面的. ...

  3. Network Saboteur 分类: 搜索 POJ 2015-08-09 19:48 7人阅读 评论(0) 收藏

    Network Saboteur Time Limit: 2000MS Memory Limit: 65536K Total Submissions: 10147 Accepted: 4849 Des ...

  4. 使用oracle写if判断

    DECLARE L_X INT; BEGIN SELECT COUNT(*) INTO L_X FROM SYSTEMROLEFUNCTION WHERE ROLEID = '1'; IF L_X & ...

  5. Uva 10118 免费糖果

    题目链接:https://uva.onlinejudge.org/external/101/10118.pdf 参考:http://www.cnblogs.com/kedebug/archive/20 ...

  6. MySQL常用操作总结

    MySQL常用操作 前提条件:已安装MySQL. 学习目标:用一条sql语句写出A和B的剩余数量 AA表 BB表 以上为一道面试题,接下来由这道面试题来回顾一些数据库的基本操作. 登录MySQL su ...

  7. Repeater的Command操作

    Repeater的Command操作 1.ItemCommand事件 :在Repeater中所有能触发事件的控件,都会来触发这一个事件 后台创建:在Page_Load中 Repeater1.ItemC ...

  8. qbxt十一系列一

    希望[题目描述]网页浏览器者有后退与前进按钮,一种实现这两个功能的方式是用两个栈,“前进栈”.“后退栈”.这里你需要实现以下几个功能:BACK: 如果“后退栈”为空则忽略此命令. 否则将当前两面压入“ ...

  9. 在nginx下去掉ci框架url中的index.php

    ci框架默认的url规则中带有应用的入口文件,例如: example.com/index.php/news/article/my_article 在以上URL中带有入口文件index.PHP,这样的U ...

  10. 【Java】List集合按数量分组

    有时候,我们需要将大的集合按指定的数量分割成若干个小集合.(比如:集合作为SQL中IN的参数,而SQL又有长度限制,所以需要分批分几次进行查询) 虽然此需求感觉不常见,但偶也写过几次类似的方法,故记录 ...