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/
  • 相关阅读:
    BZOJ 1191 HNOI2006 超级英雄hero
    BZOJ 2442 Usaco2011 Open 修建草坪
    BZOJ 1812 IOI 2005 riv
    OJ 1159 holiday
    BZOJ 1491 NOI 2007 社交网络
    NOIP2014 D1 T3
    BZOJ 2423 HAOI 2010 最长公共子序列
    LCA模板
    NOIP 2015 D1T2信息传递
    数据结构
  • 原文地址:https://www.cnblogs.com/xcysblog/p/9343539.html
Copyright © 2011-2022 走看看