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;
}
时间: 2024-12-18 18:45:09

HDU 3247 Resource Archiver (AC自己主动机 + BFS + 状态压缩DP)的相关文章

hdu 3247 Resource Archiver(AC自动机+BFS+DP)

题目链接:hdu 3247 Resource Archiver 题目大意:给定N个需要包含的串,M个不能包含的串,问说满足的最短字符串长度. 解题思路:直接对所有串建立AC自动机,不能满足的串用同一种标记即可.然后处理出所有属于需要包含串的单词节 点,用BFS处理出两两之间的距离,并且过程中是不能经过禁止节点.这样做的原因是节点的个数很多,如果对所有的 节点进行dp的话空间都不够.剩下的就是dp了. #include <cstdio> #include <cstring> #inc

HDU 3247 Resource Archiver AC自动机 + bfs + 状态压缩dp

题意:给定你n个文本串 ,m个模式串,怎么构造最短的新的文本串使得这个新的文本串包含n个文本串的所有信息且文本串的长度最短且不包含模式串. 解题思路:这里看题解撸的,首先我们算出两两文本串的距离(end数组标记文本和模式串的值不同,利用这个进行bfs算出两两之间的最短距离,注意到这里模式串的end是不能走到的.这里也不需要松弛操作),然后因为n只有10这么大,所以我们可以状态压缩  ,dp[i][j] 表示 压缩后状态为 i(二进制压缩,每i位表示第i个是否在)且 以j结尾的文本串的最小花费.这

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 n

hdu 2825 Wireless Password(ac自己主动机&amp;amp;dp)

Wireless Password Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 4022    Accepted Submission(s): 1196 Problem Description Liyuan lives in a old apartment. One day, he suddenly found that there

HDU 4539 郑厂长系列故事——排兵布阵 (状态压缩DP)

中文题,题意不再累赘. 思路:对于第 i 行的放士兵,影响它的只有第 i-1 行和 i-2 行,所以暴力枚举符合这三行的状态 state[i],state[j],state[k].  接下来就是二进制的巧妙应用了. 具体题解看代码注释!!! #include<cstdio> #include<stdlib.h> #include<string.h> #include<string> #include<map> #include<cmath&

POJ 3691 &amp;amp; HDU 2457 DNA repair (AC自己主动机,DP)

http://poj.org/problem?id=3691 http://acm.hdu.edu.cn/showproblem.php?pid=2457 DNA repair Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 5690   Accepted: 2669 Description Biologists finally invent techniques of repairing DNA that contain

[AC自动机+spfa+状压dp] hdu 3247 Resource Archiver

题意: 给n个本源串,m个病毒串 求一个最多的长度的单词包含所有的本源串并不包含任意一个病毒串 串均为01串 思路: 只有10个本源串 一开始想的是直接建立完trie图 然后在图上直接spfa 结果发现 dis[60005][1030] 超内存了 这个时候就要想到 其实只有节点的mark值大于0的节点是我们需要用的 就是那些含有状压权值的节点 那么我们先记录下这些节点是哪些 然后发现其实这些不到100个节点 所以跑100遍spfa 求出两两之间的最短路 然后用这个距离 去状压dp 数组就成了 d

hdu 3502 bfs+状态压缩dp

题意是给你n*m的矩阵     每个单位有一个数,-1表示不能走   >=0表示有有多少个能量能获得    问从左上角到右下角能获得的做大能量值(走一步消耗1单位能量) 思路:  先bfs求出所有线之间的最短距离(当然  有用的只有有能量值的点和起点,终点) 然后状态压缩dp  找到最大能量值    这里有几个注意的地方 状态尽量从1开始    减少数组的空间(爆了一次)   其次是bfs是只搜有能量的点     其它都差不多: #include<stdio.h> #include<

poj 2778 AC自己主动机 + 矩阵高速幂

// poj 2778 AC自己主动机 + 矩阵高速幂 // // 题目链接: // // http://poj.org/problem?id=2778 // // 解题思路: // // 建立AC自己主动机,确定状态之间的关系,构造出,走一步 // 能到达的状态矩阵,然后进行n次乘法,就能够得到状态间 // 走n步的方法数. // 精髓: // 1):这个ac自己主动机有一些特别,根节点是为空串,然而 // 每走一步的时候,假设没法走了,这时候,不一定是回到根 // 节点,由于有可能单个的字符