[USACO15FEB]审查

一、题目

点此看题

二、解法

本题最重要的条件是:列表中的单词不会出现一个单词是另一个单词子串的情况,所以下图的情况是不可能出现的(大包含小,却删掉了小)。
在这里插入图片描述
所以就是 AC \text{AC} 自动机板题了,用栈维护一下就行了,时间复杂度 O ( n ) O(n)

#include <cstdio>
#include <cstring>
#include <queue>
using namespace std;
const int M = 100005;
int read()
{
    int x=0,flag=1;
    char c;
    while((c=getchar())<'0' || c>'9') if(c=='-') flag=-1;
    while(c>='0' && c<='9') x=(x<<3)+(x<<1)+(c^48),c=getchar();
    return x*flag;
}
int n,m,top,h[M],w[M];
char s[M],t[M];
struct Automaton
{
    int c[M][26],val[M],fail[M],cnt;
    void ins(char *s)
    {
        int len=strlen(s),now=0;
        for(int i=0; i<len; i++)
        {
            int v=s[i]-'a';
            if(!c[now][v]) c[now][v]=++cnt;
            now=c[now][v];
        }
        val[now]=len;
    }
    void build()
    {
        queue<int> q;
        for(int i=0; i<26; i++) if(c[0][i]) q.push(c[0][i]);
        while(!q.empty())
        {
            int t=q.front();
            q.pop();
            for(int i=0; i<26; i++)
                if(c[t][i]) fail[c[t][i]]=c[fail[t]][i],q.push(c[t][i]);
                else c[t][i]=c[fail[t]][i];
        }
    }
    void solve()
    {
        m=strlen(s);
        for(int i=0,now=0; i<m; i++)
        {
            int v=s[i]-'a';
            now=c[now][v];
            h[++top]=i;
            w[top]=now;
            if(val[now])
            {
                top-=val[now];
                now=w[top];
            }
        }
        for(int i=1; i<=top; i++)
            printf("%c",s[h[i]]);
        puts("");
    }
} AC;
int main()
{
    scanf("%s",s);
    n=read();
    for(int i=1; i<=n; i++)
    {
        scanf("%s",t);
        AC.ins(t);
    }
    AC.build();
    AC.solve();
}
发布了257 篇原创文章 · 获赞 13 · 访问量 6747

猜你喜欢

转载自blog.csdn.net/C202044zxy/article/details/104121559