• 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
    ", ac.solve(n));
        }
        return 0;
    }
    


  • 相关阅读:
    ubuntu16.04下安装Wineqq+Firefox flash安装+搜狗输入法+截图软件ksnatshot
    集合数据类型
    hadoop2.7ubuntu伪分布式搭建
    广播变量&累加变量
    第一行代码----服务的最佳实践(体会,问题,解决)
    c语言中产生随机数
    如何把StringBuilder类型字符串中的字符换位置
    判断字母的大小写方法(3种)
    方法的参数个数讨论。
    中缀表达式->后缀表达式
  • 原文地址:https://www.cnblogs.com/brucemengbm/p/7122942.html
Copyright © 2020-2023  润新知