HDU 3247 Resource Archiver[AC自动机+最短路+dp]
http://acm.hdu.edu.cn/showproblem.php?pid=3247
题意:给n个源代码串,m个病毒串(都是01串),求最短的串,包含所有源代码串,但不包含任何病毒串,输出这个最短串的长度。
(题目没说如果不存在该输出什么,那应该就是保证一定存在吧。即没有任何一个病毒串是源代码串的子串)
思路:将所有串都加入自动机中,预处理出所有代码串之间的最短路(不经过病毒串的最短路),然后问题就变成了从trie树根节点开始,经过每个代码串结点各一次的最短路径,类似于TSP,用状压dp可解。
#include<cassert>
#include<algorithm>
#include<cmath>
#include<iostream>
#include<cstdio>
#include<cstring>
#include<vector>
#include<set>
#include<queue>
#include<map>
using namespace std;
#define rep(i,f,t) for(int i = (f), _end = (t); i <= _end; ++i)
#define dep(i,f,t) for(int i = (f), _end = (t); i >= _end; --i)
#define clr(c,x) memset(c,x,sizeof(c));
#define debug(x) cout<<"debug "<<x<<endl;
const int INF = 0x3f3f3f3f;
inline int RD(){ int res; scanf("%d",&res); return res; }
#define Rush for(int casn = RD(), cas = 1; cas <= casn; ++cas)
//***************************************************************
const int maxs = 60006;
int dis[11][11];
int dp[1025][11];
struct Trie{
int next[maxs][2];
int end[maxs];
int fail[maxs];
int sz;
void init(){
sz = fail[0] = end[0] = 0;
clr(next[0], 0);
}
int newnode(){
++sz;
fail[sz] = end[sz] = 0;
clr(next[sz], 0);
return sz;
}
int insert(char *s, int id){
int u = 0;
while(*s){
int nid = *s++ - '0';
int &v = next[u][nid];
if(!v) v = newnode();
u = v;
if(end[u] < 0)return 0;
}
if(id > 0){
if(next[u][0] || next[u][1] || end[u])return -1;
}else{
next[u][0] = next[u][1] = 0;
}
end[u] = id;
return u;
}
void build(){
queue<int> q;
rep(c,0,1) if(next[0][c])q.push(next[0][c]);
while(!q.empty()){
int u = q.front();
q.pop();
int fu = fail[u];
if(end[fu] == -1){
end[u] = -1;
}
rep(c,0,1){
int &v = next[u][c];
if(v){
q.push(v);
fail[v] = next[fu][c];
}else{
v = next[fu][c];
}
}
}
}
int dt[maxs];
void bfs(int s){
clr(dt, -1);
queue<int> q;
dt[s] = 0;
q.push(s);
while(!q.empty()){
int u = q.front();
q.pop();
if(u == 0 || end[u] > 0) dis[end[s]][end[u]] = dt[u];
rep(c,0,1){
int v = next[u][c];
if(end[v] < 0 || dt[v] >= 0)continue;
dt[v] = dt[u] + 1;
q.push(v);
}
}
}
int solve(int n){
clr(dp, INF);
rep(i,1,n){
dp[1<<(i-1)][i] = dis[0][i];
}
rep(S,1,(1<<n)-2){
rep(i,1,n)if(S>>(i-1)&1){
if(dp[S][i] == INF)while(1)puts("**");
rep(j,1,n)if( !(S>>(j-1)&1) ){
int &nxt = dp[S|(1<<(j-1))][j];
nxt = min(nxt, dp[S][i] + dis[i][j]);
}
}
}
return *min_element(dp[(1<<n)-1]+1, dp[(1<<n)-1]+n+1);
}
}ac;
char tmp[50005];
int mp[11];
int main(){
int n,m;
while(scanf("%d%d",&n,&m), n){
ac.init();
clr(dis, INF);
for(int i = 1; i <= n; ){
scanf("%s",tmp);
int t = ac.insert(tmp, i);
if(t > 0){
dis[0][i] = strlen(tmp);
mp[i] = t;
++i;
}else{
--n;
}
}
rep(i,1,m){
scanf("%s",tmp);
ac.insert(tmp, -1);
}
ac.build();
rep(i,1,n){
ac.bfs(mp[i]);
}
int ans = ac.solve(n);
printf("%d\n",ans);
}
return 0;
}
版权声明:本文为博主原创文章,未经博主允许不得转载。