Time Limit: 20000/10000 MS (Java/Others)    Memory Limit: 100000/100000 K (Java/Others)

Total Submission(s): 2302    Accepted Submission(s): 724


Problem Description
Great! Your new software is almost finished! The only thing left to do is archiving all your n resource files into a big one.

Wait a minute… you realized that it isn’t as easy as you thought. Think about the virus killers. They’ll find your software suspicious, if your software contains one of the m predefined virus codes. You absolutely don’t want this to happen.

Technically, resource files and virus codes are merely 01 strings. You’ve already convinced yourself that none of the resource strings contain a virus code, but if you make the archive arbitrarily, virus codes can still be found somewhere.

Here comes your task (formally): design a 01 string that contains all your resources (their occurrences can overlap), but none of the virus codes. To make your software smaller in size, the string should be as short as possible.
 

Input
There will be at most 10 test cases, each begins with two integers in a single line: n and m (2 <= n <= 10, 1 <= m <= 1000). The next n lines contain the resources, one in each line. The next m lines contain the virus codes, one in each line. The resources
and virus codes are all non-empty 01 strings without spaces inside. Each resource is at most 1000 characters long. The total length of all virus codes is at most 50000. The input ends with n = m = 0.
 

Output
For each test case, print the length of shortest string.
 

Sample Input

2 2
1110
0111
101
1001
0 0
 

Sample Output

5
 

题意:给你n个01串和m个01串,让你构造一个最短的字符串要包含前n个,但不能包含m中的任意一个。

思路:先把(n+m)个串都放进trie图中,那么n(n<=10)个节点是否已经经过的状态可以用二进制表示出来,然后把m个串的尾节点都设为危险节点,然后进行dp。容易想到的dp是用dp[j][state]表示走到第j个节点,当前n个串的储存情况为state所需要的最少步数,但是这样的时间复杂度是60000*1024*10超时了。所以我们会发现其实在dp过程中,很多节点都是没有用的,即对n个点状态没有影响,只有到n个字符串尾节点对应的trie图节点,state状态才会改变,所以我们考虑先在根节点,n个尾节点在trie图中对应的节点两两之间求最短路即最少步数,然后就在这n个点中状压dp就行了。

#include<iostream>
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<math.h>
#include<vector>
#include<map>
#include<set>
#include<queue>
#include<stack>
#include<string>
#include<algorithm>
using namespace std;
typedef long long ll;
#define inf 99999999
#define pi acos(-1.0)
#define maxnode 60050
int dp[20][1030],dist[20][20],vis[maxnode];
int n,m;
map<int,int>jiedianhao;
map<int,int>chuanhao;
map<int,int>::iterator it; struct trie{
int sz,root,val[maxnode],next[maxnode][2],fail[maxnode];
int q[1111111],q1[1111111][2];
void init(){
int i;
sz=root=0;
val[0]=0;
for(i=0;i<2;i++){
next[root][i]=-1;
}
jiedianhao[0]=0;
chuanhao[0]=0;
}
int idx(char c){
return c-'0';
}
void charu(char *s,int num){
int i,j,u=0;
int len=strlen(s);
for(i=0;i<len;i++){
int c=idx(s[i]);
if(next[u][c]==-1){
sz++;
val[sz]=0;
next[u][c]=sz;
u=next[u][c];
for(j=0;j<2;j++){
next[u][j]=-1;
}
}
else{
u=next[u][c];
}
}
if(num==-1)val[u]=-1;
else{
jiedianhao[num]=u;
chuanhao[u]=num;
val[u]|=(1<<num-1);
}
}
void build(){
int i,j;
int front,rear;
front=1;rear=0;
for(i=0;i<2;i++){
if(next[root][i]==-1 ){
next[root][i]=root;
}
else{
fail[next[root][i] ]=root;
rear++;
q[rear]=next[root][i];
}
}
while(front<=rear){
int x=q[front];
if(val[fail[x] ]==-1 )val[x]=-1;
else val[x]|=val[fail[x] ];
front++;
for(i=0;i<2;i++){
if(next[x][i]==-1){
next[x][i]=next[fail[x] ][i]; }
else{
fail[next[x][i] ]=next[fail[x] ][i];
rear++;
q[rear]=next[x][i];
} }
}
}
void debug(){
int i,j;
for(j=0;j<=sz;j++){
printf("--->%d %d %d %d\n",j,val[j],next[j][0],next[j][1]);
}
}
void bfs()
{
int i,j,state,x,t,tt,xx;
memset(dist,0,sizeof(dist));
for(i=0;i<=n;i++){
for(j=0;j<=sz;j++)vis[j]=0;
vis[jiedianhao[i] ]=1;
if(i!=0)state=(1<<(i-1) );
else state=0;
int front=1;
int rear=0;
rear++;
q1[rear][0]=jiedianhao[i];q1[rear][1]=0;
while(front<=rear){
x=q1[front][0];t=q1[front][1];
front++;
for(j=0;j<2;j++){
xx=next[x][j];
tt=t+1;
if(vis[xx])continue;
if(val[xx]==-1)continue;
vis[xx]=1;
if(val[xx]!=0){
state|=val[xx];
dist[i][chuanhao[xx] ]=t+1;
if(state==(1<<n)-1)break;
}
rear++;
q1[rear][0]=xx;q1[rear][1]=tt;
}
if(state==(1<<n)-1)break;
}
}
}
void solve(){
int i,j,state,state1;
for(i=0;i<=n;i++){
for(state=0;state<(1<<n);state++ ){
dp[i][state]=inf;
}
}
dp[0][0]=0;
for(state=0;state<(1<<n);state++){ //这个状压dp和tsp问题中的有些不同,这里是由已知的状态去推未知的状态,因为可能一个字符串包含其他字符串。
for(i=0;i<=n;i++){
if(dp[i][state]!=inf){
for(j=1;j<=n;j++){
dp[j][state|val[jiedianhao[j] ] ]=min(dp[j][state|val[jiedianhao[j] ] ],dp[i][state ]+dist[i][j] );
}
}
}
}
int minx=inf;
for(i=0;i<=n;i++){
minx=min(minx,dp[i][(1<<n)-1]);
}
printf("%d\n",minx);
}
}ac; char s[1005],str[50050];
int main()
{
int i,j;
while(scanf("%d%d",&n,&m)!=EOF)
{
if(n==0 && m==0)break;
jiedianhao.clear();
chuanhao.clear();
ac.init();
for(i=1;i<=n;i++){
scanf("%s",s);
ac.charu(s,i);
}
for(i=1;i<=m;i++){
scanf("%s",str);
ac.charu(str,-1);
}
ac.build();
ac.bfs();
ac.solve();
}
return 0;
}

hdu3247Resource Archiver (AC自动机+最短路+状压dp)的更多相关文章

  1. HDU2825 Wireless Password 【AC自动机】【状压DP】

    HDU2825 Wireless Password Problem Description Liyuan lives in a old apartment. One day, he suddenly ...

  2. 【AC自动机】【状压dp】【滚动数组】hdu6086 Rikka with String

    给你m个01串,问你有多少个长度为2L的01串,满足前半段倒置取反后等于后半段,并且包含所有的m个01串. 考虑单词完全在中线前面或者后面的情况,直接将单词及其倒置取反插入AC自动机,AC自动机每个结 ...

  3. 【AC自动机】【状压dp】hdu2825 Wireless Password

    f(i,j,S)表示当前字符串总长度为i,dp到AC自动机第j个结点,单词集合为S时的方案数. 要注意有点卡常数,注意代码里的注释. #include<cstdio> #include&l ...

  4. HDU3247 Resource Archiver —— AC自动机 + BFS最短路 + 状压DP

    题目链接:https://vjudge.net/problem/HDU-3247 Resource Archiver Time Limit: 20000/10000 MS (Java/Others)  ...

  5. HDU 4568 Hunter 最短路+状压DP

    题意:给一个n*m的格子,格子中有一些数,如果是正整数则为到此格子的花费,如果为-1表示此格子不可到,现在给k个宝藏的地点(k<=13),求一个人从边界外一点进入整个棋盘,然后拿走所有能拿走的宝 ...

  6. 最短路+状压DP【洛谷P3489】 [POI2009]WIE-Hexer

    P3489 [POI2009]WIE-Hexer 大陆上有n个村庄,m条双向道路,p种怪物,k个铁匠,每个铁匠会居住在一个村庄里,你到了那个村庄后可以让他给你打造剑,每个铁匠打造的剑都可以对付一些特定 ...

  7. 【BZOJ1097】[POI2007]旅游景点atr 最短路+状压DP

    [BZOJ1097][POI2007]旅游景点atr Description FGD想从成都去上海旅游.在旅途中他希望经过一些城市并在那里欣赏风景,品尝风味小吃或者做其他的有趣的事情.经过这些城市的顺 ...

  8. ACM-ICPC2018南京网络赛 AC Challenge(一维状压dp)

    AC Challenge 30.04% 1000ms 128536K   Dlsj is competing in a contest with n (0 < n \le 20)n(0<n ...

  9. 【CodeVS2800】 送外卖 最短路+状压DP

    首先求出各点之间的最短路,floyed即可,注意是0-n. 然后考虑状压,f[i][j]表示状态为i时访问j点时的最短路和,1表示访问,0表示未访问,然后第j个点所在的位置就是(1<<j) ...

随机推荐

  1. 【Java基础】Java10 新特性

    Java10 新特性 局部变量类型推断 局部变量的显示类型声明,常常被认为是不必须的. 场景一:类实例化时.在声明一个变量时,总是习惯了敲打两次变量类型,第一次用于声明变量类型,第二次用于构造器. 场 ...

  2. 一条查询SQl是怎样执行的

    MySQL的逻辑架构图 大体来说,MySQL可以分为Server层和存储引擎层两部分. Server层包括连接器.查询缓存.分析器,优化器等,涵盖MySQL的大多核心服务功能,以及所有的内置函数,存储 ...

  3. 容器编排系统K8s之Prometheus监控系统+Grafana部署

    前文我们聊到了k8s的apiservice资源结合自定义apiserver扩展原生apiserver功能的相关话题,回顾请参考:https://www.cnblogs.com/qiuhom-1874/ ...

  4. iTerm2 实现 ssh 自动登录,并使用 Zmodem 实现快速传输文件

    原文链接:https://fuckcloudnative.io/posts/iterm2-auto-login/ 对于 YAML 工程师来说,我们经常需要 ssh 登录不同的服务器,每次登录时都要经历 ...

  5. 【Linux】记一次xfs分区数据恢复

    项目有一块磁盘无法挂载,而且还没有做RAID.... # mount /dev/sda /xxx 报错 mount: special device /dev/sda/ does not exist   ...

  6. CTF------pwn笔记

    地址:http://pwnable.kr/play.php 题目: 使用MobaXterm连接(当然也可以使用别的软件进行连接,用的顺手就行) 连接成功后所以"ls"命令查看目录 ...

  7. Pandas应用案例-股票分析:使用tushare包获取股票的历史行情数据进行数据分析

    目标: 使用tushare包获取股票的历史行情数据 输出该股票所有收盘比开盘上涨3%以上的日期 输出该股票所有开盘比前日收盘跌幅超过2%以上的日期 假如为我们从2010年1月1日开始,每月第一个交易日 ...

  8. 前端开发好帮手,eslint配置全知道

    eslint让人又爱又恨,原因在于它的默认配置非常严格,动则一个小提示就直接报错不给运行.而在开发调试的过程中,我们想时时得到运行效果,它的严格又很烦. 在安装eslint后,我们可以在package ...

  9. 入门OJ:售货员的难题

    题目描述 某乡有n个村庄(1<n<15),有一个售货员,他要到各个村庄去售货,各村庄之间的路程s(0<s<1000)是已知的,且A村到B村与B村到A村的路大多不同.为了提高效率 ...

  10. 技术基础 | Apache Cassandra 4.0基准测试

    Apache Cassandra 4.0已经发布了Beta版,这是第一个支持JDK 11及更高JDK版本的Cassandra版本.   时延对于Apache Cassandra用户来说是个显而易见的关 ...