zoukankan      html  css  js  c++  java
  • BZOJ1195 : [HNOI2006]最短母串

    BZOJ1195 : [HNOI2006]最短母串

    用最短方案中字典序最小的字符串包含所有给定字符串

    看空间比较小就写状压了

    好像直接bfs也行

    然而这是一种状压dp的做法

    设 f[s][i] 为当前在 AC自动机 上编号为 i 的节点,已选择过的字符串集合为 s 的状态

    直接大力转移即可

    转移到的第一个选择了全集的 s 的时候直接退出 输出方案

    由于要输出方案,需要对每个状态记录它的 pre状态 和转移过来的 pre节点,这样方便输出

    因为在 AC自动机 上是按字典序枚举的

    这样好像就跟搜索差不多了


    完整代码:

    #include<algorithm>
    #include<iostream>
    #include<cstdlib>
    #include<cstring>
    #include<cctype>
    #include<cstdio>
    #include<queue>
    using namespace std;
    
    typedef long long ll;
    const int MAXN = 15, MAXL = 55;
    
    struct Node{
        short nxt[26], tag, curchar;
        Node() {memset(nxt, 0, sizeof(nxt)); tag = 0;}
    }t[MAXL * MAXN];
    struct DP{
        short len, preS, preNo;
        DP(short lenth = 0, short prestt = 0, short prenum = 0) {len = lenth; preS = prestt; preNo = prenum;}
    }f[(1 << 12)][MAXL * MAXN];
    short n, ptr, Root, dst, top;
    short fail[MAXN * MAXL], stk[MAXN * MAXL];
    char str[MAXL];
    bool vis[(1 << 12)][MAXL * MAXN];
    
    inline short newnode() {
        return ++ptr;
    }
    inline void Insert(char *s, short No) {
        short len = strlen(s), cur = Root;
        for(short i = 0; i < len; ++i) {
            register short x = s[i] - 'A';
            if(!t[cur].nxt[x]) {
                t[cur].nxt[x] = newnode();
                t[t[cur].nxt[x]].curchar = s[i];
            }
            cur= t[cur].nxt[x];
        }
        t[cur].tag |= (1 << (No - 1));
        return;
    }
    inline void getfail() {
        queue<short> q;
        short cur = Root;
        for(short i = 0; i < 26; ++i) {
            if(t[cur].nxt[i]) {
                q.push(t[cur].nxt[i]);
                fail[t[cur].nxt[i]] = 0;
            }
        }
        while(!q.empty()) {
            short cur = q.front(); q.pop();
            for(short i = 0; i < 26; ++i) {
                register short son = t[cur].nxt[i];
                if(!t[cur].nxt[i]) {
                    t[cur].nxt[i] = t[fail[cur]].nxt[i];
                    continue;
                }
                fail[son] = t[fail[cur]].nxt[i];
                t[son].tag |= t[fail[son]].tag;
                q.push(son);
            }
        }
        return;
    }
    inline DP dp() {
        queue<pair<short, short> > q;
        short cur = Root, s = 0;
        q.push(make_pair(cur, s));
        f[s][cur].len = 0;
        while(!q.empty()) {
            cur = q.front().first; s = q.front().second; q.pop();
            for(short i = 0; i < 26; ++i) {
                register short son = t[cur].nxt[i];
                if(t[son].tag && ((s | t[son].tag) != s)) {
                    if(f[s | t[son].tag][son].len > f[s][cur].len + 1) {
                        f[s | t[son].tag][son] = DP(f[s][cur].len + 1, s, cur);
                    }
                    if((s | t[son].tag) == dst) {
                    	stk[++top] = t[son].curchar;
                        return f[s | t[son].tag][son];
                    }
                    if(!vis[(s | t[son].tag)][son]) {
                        q.push(make_pair(son, (s | t[son].tag)));
                        vis[(s | t[son].tag)][son] = true;
                    }
                } else {
                    if(f[s][son].len > f[s][cur].len + 1) {
                    	f[s][son] = DP(f[s][cur].len + 1, s, cur);
                    }
                    if(!vis[s][son]) {
                        q.push(make_pair(son, s));
                        vis[s][son] = true;
                    }
                }
            }
        }
    }
    inline void write(DP res) {
        int st = res.preS, cur = res.preNo, tmp;
        while(cur) {
            stk[++top] = t[cur].curchar;
            tmp = st;
            st = f[st][cur].preS;
            cur = f[tmp][cur].preNo;
        }
        while(top) {
            putchar(stk[top--]);
        }
        putchar('
    ');
        return;
    }
    
    int main() {
        scanf("%hd", &n);
        dst = (1 << n) - 1;
        for(short i = 1; i <= n; ++i) {
            scanf("%s", str);
            Insert(str, i);
        }
        getfail();
        for(short i = (1 << 12) - 1; i >= 0; --i) {
        	for(short j = 825 - 1; j >= 0; --j) {
        		f[i][j].len = 32765;
        	}
        }
        write(dp());
        return 0;
    }
    /*
    6
    AA
    AAB
    AB
    A
    C
    AA
    */
    
    禁止诸如开发者知识库/布布扣/码迷/学步园/马开东等 copy 他人博文乃至博客的网站转载 ,用户转载请注明出处:https://www.cnblogs.com/xcysblog/
  • 相关阅读:
    哈希和不可哈希
    TCP/IP 学习笔记1 浅谈TCP和UDP
    让我们来开发一种更类似人脑的神经网络吧(三)
    关于用CUDA优化三层反传神经网络算法
    让我们来开发一种更类似人脑的神经网络吧(二)
    让我们来开发一种更类似人脑的神经网络吧(六)
    Matlab笔记
    记忆的模式
    让我们来开发一种更类似人脑的神经网络吧(五)
    总结一下感受器官和大脑的通信原理
  • 原文地址:https://www.cnblogs.com/xcysblog/p/9343539.html
Copyright © 2011-2022 走看看