HDU3247 Resource Archiver(AC自动机+BFS+DP)
题目,求最短的包含所有n个DNA片段且不包含任何一个病毒片段的序列。
容易用所有DNA片段和病毒片段建一个AC自动机,构造fail时处理一下各个结点后缀是DNA或者病毒的情况,然后dp[S][u]表示包含DNA片段的集合是S的且后缀状态是自动机第u个结点的最短序列长度,然后顺着AC自动机避开病毒串转移。
不过构建的AC自动机结点上限60000左右,集合有1024个状态,这样内存开不下。看了题解,原来不必要考虑自动机所有结点——
- dp[S][u]表示包含DNA片段集合是S且后缀是第u个DNA片段的最短序列长度
- 通过BFS预处理出各个DNA片段到其他DNA片段在AC自动机上的距离,要注意某些DNA片段的后缀包含其他DNA片段的情况,还有跳过后缀包含病毒串的结点。
- 转移就是dp[S][u]=max(dp[S-{u}][v]+dist[v][u])(v∈S-{u})
这个解法的正确性我还得消化消化。。
#include<cstdio>
#include<cstring>
#include<queue>
#include<algorithm>
using namespace std;
#define INF (1<<29)
#define MAXN 66666
int tn,ch[MAXN][],fail[MAXN],flag[MAXN];
int idx[];
void insert(char *s,int k){
int x=;
for(int i=; s[i]; ++i){
int y=s[i]-'';
if(ch[x][y]==) ch[x][y]=++tn;
x=ch[x][y];
}
if(k==- || flag[x]==-) flag[x]=-;
else{
idx[k]=x;
flag[x]|=(<<k);
}
}
int que[MAXN],front,rear;
void getfail(){
memset(fail,,sizeof(fail));
front=rear=;
if(ch[][]) que[rear++]=ch[][];
if(ch[][]) que[rear++]=ch[][];
while(front<rear){
int x=que[front++];
for(int i=; i<; ++i){
if(ch[x][i]){
que[rear++]=ch[x][i];
fail[ch[x][i]]=ch[fail[x]][i];
if(flag[ch[x][i]]==- || flag[ch[fail[x]][i]]==-) flag[ch[x][i]]=-;
else flag[ch[x][i]]|=flag[ch[fail[x]][i]];
}else ch[x][i]=ch[fail[x]][i];
}
}
} int n,m,dist[MAXN],G[][];
void BFS(int k){
memset(dist,,sizeof(dist));
dist[idx[k]]=;
front=rear=;
que[rear++]=idx[k];
while(front<rear){
int x=que[front++];
if(flag[x]){
for(int i=; i<n; ++i){
if(((flag[x]>>i)&)==) continue;
G[k][i]=min(G[k][i],dist[x]-);
}
}
for(int i=; i<; ++i){
int y=ch[x][i];
if(flag[y]==- || dist[y]) continue;
dist[y]=dist[x]+;
que[rear++]=y;
}
}
}
int d[<<][],len[];
int main(){
char str[];
while(~scanf("%d%d",&n,&m) && (n||m)){
tn=;
memset(ch,,sizeof(ch));
memset(flag,,sizeof(flag));
for(int i=; i<n; ++i){
scanf("%s",str);
insert(str,i);
len[i]=strlen(str);
}
for(int i=; i<m; ++i){
scanf("%s",str);
insert(str,-);
}
getfail();
for(int i=; i<n; ++i){
for(int j=; j<n; ++j) G[i][j]=INF;
}
for(int i=; i<n; ++i){
BFS(i);
}
for(int i=; i<(<<n); ++i){
for(int j=; j<n; ++j) d[i][j]=INF;
}
for(int i=; i<n; ++i){
d[<<i][i]=len[i];
}
for(int i=; i<(<<n); ++i){
for(int j=; j<n; ++j){
if(((i>>j)&)==) continue;
for(int k=; k<n; ++k){
if(((i>>k)&)== || j==k) continue;
d[i][j]=min(d[i][j],d[i^(<<j)][k]+G[k][j]);
}
}
}
int res=INF;
for(int i=; i<n; ++i) res=min(res,d[(<<n)-][i]);
printf("%d\n",res);
}
return ;
}
HDU3247 Resource Archiver(AC自动机+BFS+DP)的更多相关文章
- HDU3247 Resource Archiver —— AC自动机 + BFS最短路 + 状压DP
题目链接:https://vjudge.net/problem/HDU-3247 Resource Archiver Time Limit: 20000/10000 MS (Java/Others) ...
- HDU3247 Resource Archiver (AC自动机+spfa+状压DP)
Great! Your new software is almost finished! The only thing left to do is archiving all your n resou ...
- HDU 3247 Resource Archiver (AC自动机+BFS+状压DP)
题意:给定 n 个文本串,m个病毒串,文本串重叠部分可以合并,但合并后不能含有病毒串,问所有文本串合并后最短多长. 析:先把所有的文本串和病毒都插入到AC自动机上,不过标记不一样,可以给病毒标记-1, ...
- HDU - 3247 Resource Archiver (AC自动机,状压dp)
\(\quad\)Great! Your new software is almost finished! The only thing left to do is archiving all you ...
- hdu_3247_Resource Archiver(AC自动机+bfs+TSP)
题目链接:hdu_3247_Resource Archiver 题意: 有n个资源串,m个病毒串,现在要将所有的资源串整合到一个串内,并且这个串不能包括病毒串,问最短的串长为多少 题解: 将资源串和病 ...
- 【HDU3530】 [Sdoi2014]数数 (AC自动机+数位DP)
3530: [Sdoi2014]数数 Time Limit: 10 Sec Memory Limit: 512 MBSubmit: 682 Solved: 364 Description 我们称一 ...
- 关于AC自动机和DP的联系
首先是描述个大概.不说一些特殊的DP 或者借用矩阵来状态转移 (这些本质都是一样的). 只讲AC自动机和DP的关系(个人理解). AC自动机 又可以叫做状态机. 我一开始的认为.AC 自动机提供了一些 ...
- 【bzoj3530】[Sdoi2014]数数 AC自动机+数位dp
题目描述 我们称一个正整数N是幸运数,当且仅当它的十进制表示中不包含数字串集合S中任意一个元素作为其子串.例如当S=(22,333,0233)时,233是幸运数,2333.20233.3223不是幸运 ...
- BZOJ 3530 [SDOI2014]数数 (Trie图/AC自动机+数位DP)
题目大意:略 裸的AC自动机+数位DP吧... 定义f[i][x][0/1]表示已经匹配到了第i位,当前位置是x,0表示没到上限,1到上限,此时数是数量 然而会出现虚拟前导零,即前几位没有数字的情况, ...
随机推荐
- Linux内核之数据双链表
导读 Linux 内核中自己实现了双向链表,可以在 include/linux/list.h 找到定义.我们将会首先从双向链表数据结构开始介绍内核里的数据结构.为什么?因为它在内核里使用的很广泛,你只 ...
- ZeroMQ之Push与Pull (Java)
本系列文章均转自:http://blog.csdn.net/kobejayandy/article/details/20163431 在ZeroMQ中并没有绝对的服务端与客户端之分,所有的数据接收与发 ...
- HDOJ 1590
#include<stdio.h> #include<iostream> #include<stdlib.h> #include<string.h> u ...
- HM必修3
高中数学必修三 笔记与拓展 算法初步 算法是按照一定规则解决固定问题,通过对输入的某种变换产生结果. 素性测试 检验一个数是否为素数. 试除法 一个数是素数的充分必要条件是它因数个数为二.显然1和它本 ...
- 【Web】关于URL中文乱码问题
关于URL编码 一.问题的由来 URL就是网址,只要上网,就一定会用到. ...
- makefile中的自动化变量$@,$%,$
转自:http://www.2cto.com/os/201302/191344.html makefile中的自动化变量$@,$%,$ 自动化变量 模式规则中,规则的目标和依赖文件名代表了一 ...
- 【转】php json_encode中文为空的解决办法
转自:http://www.cnblogs.com/oldphper/p/4123415.html 本文列举3个方法,实现json_encode()后的string显示中文问题. 做接口时不需要,但存 ...
- sqlserver 常用语句
1.查询表中的RID RID=RowID=(fileID:pageID:slotID) SELECT sys.fn_PhysLocFormatter(%%physloc%%) AS rid,* FRO ...
- HDU 5734 Acperience (公式推导) 2016杭电多校联合第二场
题目:传送门. #include <iostream> #include <algorithm> #include <cstdio> #include <cs ...
- HDU 1452 Happy 2004 (逆元+快速幂+积性函数)
G - Happy 2004 Time Limit:1000MS Memory Limit:32768KB 64bit IO Format:%I64d & %I64u Subm ...