题目链接:https://vjudge.net/problem/HDU-3247

Resource Archiver

Time Limit: 20000/10000 MS (Java/Others)    Memory Limit: 100000/100000 K (Java/Others)
Total Submission(s): 3228    Accepted Submission(s): 1052

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
 
Source

题意:

给出n个(n<=10)字符串,和m(m<=1000)个单词。求包含所有字符串,并且不包含任何一个单词的长串的最短长度。

题解:

1.看到n的大小为10,并且要求包含所有字符串,就很容易想到用状压DP。

1.1 设dp[status][u]为:当前状态为status(包含了哪些字符串),并且以字符串u结尾的最短长度。设cost[u][v]为:在字符串u后面接上字符串v所需要的最短长度。由于字符串之间可以有重叠,所以cost[u][v]可能小于len[v];由于长串不能包含单词,所以在链接u、v时,之间可能还需要加一些字符以便跳过单词,所以cost[u][v]可能大于len[v]。

1.2 假如求出了cost数组,那么剩下的就是典型TSP问题了。

2. 如何求cost数组呢?

2.1 把n个字符串和m个单词都插入到AC自动机中,并且需要对字符串和单词作相应的标记。

2.2 对于每个字符串,在自动机上跑最短路,求出当前字符串与其他字符串的最短距离,在跑的时候需要跳过单词。原理:AC自动机各个状态之间的关系构成了一张图。

代码如下:

 #include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <vector>
#include <cmath>
#include <queue>
#include <stack>
#include <map>
#include <string>
#include <set>
using namespace std;
typedef long long LL;
const double EPS = 1e-;
const int INF = 2e9;
const LL LNF = 2e18;
const int MOD = 1e5;
const int MAXN = 5e4+1e4+; int n, m;
int Index[MAXN], pos[MAXN], cost[][], Len[MAXN];
int dp[<<][];
struct Trie
{
int sz, base;
int next[MAXN][], fail[MAXN], end[MAXN];
int root, L;
int newnode()
{
for(int i = ; i<sz; i++)
next[L][i] = -;
end[L++] = false;
return L-;
}
void init(int _sz, int _base)
{
sz = _sz;
base = _base;
L = ;
root = newnode();
}
int insert(char buf[], bool isVirus)
{
int len = strlen(buf);
int now = root;
for(int i = ; i<len; i++)
{
if(next[now][buf[i]-base] == -) next[now][buf[i]-base] = newnode();
now = next[now][buf[i]-base];
}
end[now] = isVirus;
return now;
}
void build()
{
queue<int>Q;
fail[root] = root;
for(int i = ; i<sz; i++)
{
if(next[root][i] == -) next[root][i] = root;
else fail[next[root][i]] = root, Q.push(next[root][i]);
}
while(!Q.empty())
{
int now = Q.front();
Q.pop();
end[now] |= end[fail[now]];
for(int i = ; i<sz; i++)
{
if(next[now][i] == -) next[now][i] = next[fail[now]][i];
else fail[next[now][i]] = next[fail[now]][i], Q.push(next[now][i]);
}
}
} int query()
{
for(int i = ; i<(<<n); i++)
for(int j = ; j<n; j++)
dp[i][j] = INF;
for(int j = ; j<n; j++)
dp[<<j][j] = Len[j]; for(int i = ; i<(<<n); i++)
for(int j = ; j<n; j++)
{
if(!(i&(<<j)) || dp[i][j]==INF) continue;
for(int k = ; k<n; k++)
if(!(i&(<<k)) && cost[j][k]!=INF)
dp[i|(<<k)][k] = min(dp[i|(<<k)][k], dp[i][j]+cost[j][k]);
} int ret = INF;
for(int i = ; i<n; i++)
ret = min(ret, dp[(<<n)-][i]);
return ret;
}
};
Trie ac; int dis[MAXN];
void BFS(int st)
{
queue<int> Q;
while(!Q.empty()) Q.pop();
for(int i = ; i<ac.L; i++)
dis[i] = INF;
dis[st] = ;
Q.push(st);
while(!Q.empty())
{
int u = Q.front(); Q.pop();
for(int i = ; i<ac.sz; i++)
{
int v = ac.next[u][i];
if(dis[v]==INF && !ac.end[v])
{
dis[v] = dis[u] + ;
Q.push(v);
}
}
}
for(int i = ; i<n; i++)
cost[Index[st]][i] = dis[pos[i]];
} char buf[MAXN];
int main()
{
while(scanf("%d%d",&n,&m)&&(n||m))
{
ac.init(,'');
memset(Index, -, sizeof(Index));
for(int i = ; i<n; i++)
{
scanf("%s", buf);
Len[i] = strlen(buf);
pos[i] = ac.insert(buf, false);
Index[pos[i]] = i;
}
for(int i = ; i<m; i++)
{
scanf("%s", buf);
ac.insert(buf, true);
}
ac.build();
for(int i = ; i<n; i++)
BFS(pos[i]); int ans = ac.query();
printf("%d\n", ans);
}
}

HDU3247 Resource Archiver —— AC自动机 + BFS最短路 + 状压DP的更多相关文章

  1. 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 ...

  2. HDU 3247 Resource Archiver (AC自动机+BFS+状压DP)

    题意:给定 n 个文本串,m个病毒串,文本串重叠部分可以合并,但合并后不能含有病毒串,问所有文本串合并后最短多长. 析:先把所有的文本串和病毒都插入到AC自动机上,不过标记不一样,可以给病毒标记-1, ...

  3. hdu3247Resource Archiver (AC自动机+最短路+状压dp)

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

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

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

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

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

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

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

  7. hdu_3247_Resource Archiver(AC自动机+bfs+TSP)

    题目链接:hdu_3247_Resource Archiver 题意: 有n个资源串,m个病毒串,现在要将所有的资源串整合到一个串内,并且这个串不能包括病毒串,问最短的串长为多少 题解: 将资源串和病 ...

  8. HDU - 3247 Resource Archiver (AC自动机,状压dp)

    \(\quad\)Great! Your new software is almost finished! The only thing left to do is archiving all you ...

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

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

随机推荐

  1. ntp时间服务同步

    第一种方式:同步到网络时间服务器 # ntpdate time.windows.com将硬件时间设置为当前系统时间. #hwclock –w 加入crontab: 30 8 * * * root /u ...

  2. 2016.7.14 去掉Mybatis Generator生成的一堆 example

    参考资料: http://www.cnblogs.com/zerocold/p/4220955.html   mybatis generator自动生成的代码里老是有一堆example,需要改的时候, ...

  3. 导出excel文件工具类

    package com.rrz.common.utils.excel; import java.io.IOException;import java.io.OutputStream;import ja ...

  4. 【基础算法】排序-复杂排序之二(找出第K大的数)

    切割的思想是高速排序最精髓的地方.每一次切割出来的元素K一个排在第K位,所以利用这样的思想我们至少知道3点 1. 被切割出来的元素K最后一定排在第K位. 2. 在K左边的元素一定比K小或者相等. 3. ...

  5. snmp默认团体名/弱口令漏洞及安全加固

    0x00基础知识 简单网络管理协议(SNMP)被广泛用于计算机操作系统设备.网络设备等领域监测连接到网络上的设备是否有任何引起管理上关注的情况.在运行SNMP服务的设备上,若管理员配置不当运行默认团体 ...

  6. leetCode 47.Permutations II (排列组合II) 解题思路和方法

    Permutations II  Given a collection of numbers that might contain duplicates, return all possible un ...

  7. ASP.NET MVC路径引用总结

    1.关于路径: (1)绝对路径 包含站点路径的路径:<a href=”http://www.baidu.com/about.jpg”>百度</a> 站点改变路径失效: (2)相 ...

  8. Nginx 经验小结

    chmod 777 永远不要 使用 777,有时候可以懒惰的解决权限问题, 但是它同样也表示你没有线索去解决权限问题,你只是在碰运气. 你应该检查整个路径的权限,并思考发生了什么事情. 把 root ...

  9. 简单理解ThreadLocal原理和适用场景

    https://blog.csdn.net/qq_36632687/article/details/79551828?utm_source=blogkpcl2 参考文章: 正确理解ThreadLoca ...

  10. 通信协议之sdp---sdp会话协议

    (1)sdp 描述格式 (2)sdp example (3) sdp (1)sdp 描述格式 m=video 1234 RTP/AVP 96a=rtpmap:96 H264a=framerate:15 ...