首页 > 代码库 > HDU 3247 Resource Archiver (AC自己主动机 + BFS + 状态压缩DP)

HDU 3247 Resource Archiver (AC自己主动机 + BFS + 状态压缩DP)

题目链接:Resource Archiver


解析:n个正常的串。m个病毒串,问包括全部正常串(可重叠)且不包括不论什么病毒串的字符串的最小长度为多少。

AC自己主动机 + bfs + 状态压缩DP

用最短路预处理出状态的转移。能够优化非常多



AC代码:

#include <cstdio>
#include <iostream>
#include <cstring>
#include <algorithm>
#include <queue>
using namespace std;

const int INF = 0x3f3f3f3f;
struct Trie{
    int next[60010][2], fail[60010], end[60010];
    int root, L;
    int newnode(){
        for(int i=0; i<2; i++)  next[L][i] = -1;
        end[L++] = 0;
        return L-1;
    }
    void init(){
        L = 0;
        root = newnode();
    }
    void insert(char buf[], int id){
        int len = strlen(buf);
        int now = root;
        for(int i=0; i<len; i++){
            if(next[now][buf[i] - '0'] == -1)
                next[now][buf[i] - '0'] = newnode();
            now = next[now][buf[i] - '0'];
        }
        end[now] = id;
    }
    void build(){
        queue<int> Q;
        fail[root] = root;
        for(int i=0; i<2; i++)
            if(next[root][i] == -1) next[root][i] = root;
            else{
                fail[ next[root][i] ] = root;
                Q.push(next[root][i]);
            }
        while(!Q.empty()){
            int now = Q.front();
            Q.pop();
            if(end[ fail[now] ] == -1) end[now] = -1;
            else end[now] |= end[ fail[now] ];
            for(int i=0; i<2; i++)
                if(next[now][i] == -1)  next[now][i] = next[ fail[now] ][i];
                else{
                    fail[ next[now][i] ] = next[ fail[now] ][i];
                    Q.push(next[now][i]);
                }
        }
    }
    int g[11][11];
    int dp[1025][11];
    int cnt;
    int pos[11];
    int dis[60010];

    void bfs(int k){
        queue<int> q;
        memset(dis, -1, sizeof(dis));
        dis[pos[k]] = 0;
        q.push(pos[k]);
        while(!q.empty()){
            int now = q.front();
            q.pop();
            for(int i=0; i<2; i++){
                int tmp = next[now][i];
                if(dis[tmp] < 0 && end[tmp] >= 0){
                    dis[tmp] = dis[now] + 1;
                    q.push(tmp);
                }
            }
        }
        for(int i=0; i<cnt; i++)    g[k][i] = dis[pos[i]];
    }

    int solve(int n){
        pos[0] = 0;
        cnt = 1;
        for(int i=0; i<L; i++)
            if(end[i] > 0) pos[cnt++] = i;
        for(int i=0; i<cnt; i++) bfs(i);

        for(int i=0; i<(1<<n); i++)
            for(int j=0; j<cnt; j++)
                dp[i][j] = INF;
        dp[0][0] = 0;
        for(int i=0; i<(1<<n); i++)
            for(int j=0; j<cnt; j++)
                if(dp[i][j] < INF){
                    for(int k=0; k<cnt; k++){
                        if(g[j][k] < 0) continue;
                        if(j == k) continue;
                        dp[i | end[pos[k]]][k] = min(dp[i | end[pos[k]]][k], dp[i][j] + g[j][k]);
                    }
                }
        int ans = INF;
        for(int i=0; i<cnt; i++)
            ans = min(ans, dp[(1<<n)-1][i]);
        return ans;
    }
};

char buf[1010];
Trie ac;

int main(){
    #ifdef sxk
        freopen("in.txt", "r", stdin);
    #endif // sxk
    int n, m;
    while(scanf("%d%d", &n, &m) == 2){
        if(n == 0 && m == 0) break;
        ac.init();
        for(int i=0; i<n; i++){
            scanf("%s", buf);
            ac.insert(buf, 1<<i);
        }
        for(int i=0; i<m; i++){
            scanf("%s", buf);
            ac.insert(buf, -1);
        }
        ac.build();
        printf("%d\n", ac.solve(n));
    }
    return 0;
}


HDU 3247 Resource Archiver (AC自己主动机 + BFS + 状态压缩DP)