zoukankan      html  css  js  c++  java
  • [loj10061] 最短母串

    #10061. 「一本通 2.4 练习 4」最短母串

    内存限制:512 MiB 时间限制:1000 ms 标准输入输出
    题目类型:传统 评测方式:文本比较
    上传者: 1bentong
    提交    提交记录    统计    讨论    测试数据
     

    题目描述

    原题来自:HNOI 2006

    给定 n个字符串 S1,S2,⋯,Sn 要求找到一个最短的字符串 T,使得这 个字符串都是 的子串。

    输入格式

    第一行是一个正整数 n,表示给定的字符串的个数;

    以下的 n 行,每行有一个全由大写字母组成的字符串。

    输出格式

    只有一行,为找到的最短的字符串 T

    在保证最短的前提下,如果有多个字符串都满足要求,那么必须输出按字典序排列的第一个。

    样例

    样例输入

    2 
    ABCD
    BCDABC

    样例输出

    ABCDABC

    数据范围与提示

    对于全部数据,1≤n≤12,1≤∣Si∣≤50

    题意:(挂loj是因为我的解法在bzoj上T了并且我不想调QAQ)

    给你$n$个字符串,求他们的最短母串,即求一个最短字符串使得这$n$个字符串都是它的子串。若长度相同输出字典序最小的。

    题解:

    建出$AC$自动机后问题转化成找一条最短的路径覆盖所有$end$节点。

    那么我们可以考虑对每个节点维护一个压缩状态表示从根走到该点包含了哪些字符串。

    然后从根开始沿$bfs$序遍历(保证字典序最小)并记录路径,若合法则输出答案。

    这题主要是教会了我一个真理:

    当你发现某个代码已经改不出来的时候,重构代码总是会给你惊喜……

    代码:

    #include<algorithm>
    #include<iostream>
    #include<cstring>
    #include<cstdio>
    #include<queue>
    
    using namespace std;
    #define MAXN 15
    #define MAXM 605
    #define ll long long
    
    struct node{
        int son[30],s;
    }tree[MAXM];
    struct way{
        int las; char ch;
    }p[MAXM*(1<<MAXN)];
    int tot=1,nxt[MAXM];
    bool vis[MAXM][1<<MAXN];
    char str[MAXN],ans[MAXN];
    inline int read(){
        int x=0,f=1;
        char c=getchar();
        for(;!isdigit(c);c=getchar())
            if(c=='-')
                f=-1;
        for(;isdigit(c);c=getchar())
            x=x*10+c-'0';
        return x*f;
    }
    
    inline void add(int p,char *str){
        int N=strlen(str),u=1;
        for(int i=0;i<N;i++){
            int ch=str[i]-'A';
            if(!tree[u].son[ch]) 
                tree[u].son[ch]=++tot;
            u=tree[u].son[ch];
        }
        tree[u].s|=(1<<p);
        return;    
    }
    
    inline void get_nxt(){
        for(int i=0;i<26;i++) 
            tree[0].son[i]=1;
        queue<int> q; q.push(1);
        while(!q.empty()){
            int u=q.front(); q.pop();
            for(int i=0;i<26;i++){
                if(tree[u].son[i]){
                    q.push(tree[u].son[i]);
                    nxt[tree[u].son[i]]=tree[nxt[u]].son[i];
                    tree[tree[u].son[i]].s|=tree[tree[nxt[u]].son[i]].s;
                }
                else tree[u].son[i]=tree[nxt[u]].son[i];
            }
        }
        return;
    }
    
    inline void solve(int N){
        int end=(1<<N)-1;
        queue<int> q1,q2;
        q1.push(1); q2.push(0);
        int hd=1,tl=1;
        while(!q1.empty() && !q2.empty()){
            int u=q1.front();q1.pop();
            int sta=q2.front();q2.pop();
            if(sta==end){
                int cnt=0;
                for(;hd>1;hd=p[hd].las)
                    ans[++cnt]=p[hd].ch;
                for(int i=cnt;i>=1;i--)
                    printf("%c",ans[i]);
                printf("
    ");
                return;
            }
            for(int i=0;i<26;i++){
                if(!vis[tree[u].son[i]][(tree[tree[u].son[i]].s)|(sta)]){
                    vis[tree[u].son[i]][(tree[tree[u].son[i]].s)|(sta)]=1;
                    q1.push(tree[u].son[i]);
                    q2.push((tree[tree[u].son[i]].s)|(sta));
                    p[++tl].las=hd,p[tl].ch=i+'A';
                }
            }
            hd++;
        }
        return;
    }
    
    int main(){
        int N=read();
        for(int i=0;i<N;i++)
            scanf("%s",str),add(i,str);
        get_nxt(); solve(N);
        return 0;
    }
  • 相关阅读:
    洛谷.4717.[模板]快速沃尔什变换(FWT)
    BZOJ.4589.Hard Nim(FWT)
    BZOJ.1758.[WC2010]重建计划(分数规划 点分治 单调队列/长链剖分 线段树)
    BZOJ.4543.[POI2014]Hotel加强版(长链剖分 树形DP)
    Vijos.lxhgww的奇思妙想(k级祖先 长链剖分)
    Codeforces.741D.Arpa’s letter-marked tree and Mehrdad’s Dokhtar-kosh paths(dsu on tree 思路)
    Codeforces.600E.Lomsat gelral(dsu on tree)
    11.7 NOIP模拟赛
    11.5 正睿停课训练 Day16
    Maven与Nexus3.x环境构建详解
  • 原文地址:https://www.cnblogs.com/YSFAC/p/9836266.html
Copyright © 2011-2022 走看看