序列自动机【模板】

南昌邀请赛网络赛M题 Subsequence 

题意:

给你一个字符串S,长度小于1e5,

然后n次询问,n小于1e5,

每次输入一个字符串T,问T是不是S的子序列。 T长度小于1000

input:

abcdefg
3
abc
adg
cba

output:

YES
YES
NO

思路:

序列自动机其实就是先预处理出来一个数组,Next[i][j]表示在位置i的后面第一个字符j所在的位置,预处理出Next数组的复杂度就是log(N∗26)
每次询问就是log(M)的复杂度(M是每次询问字符串的长度)。

 

AC代码:

#include<bits/stdc++.h>

using namespace std;
 
const int maxn=1e5+7;
char s[maxn];
char t[maxn];
 
int Next[maxn][27];

void init(int n){
    for(int i=n-1;i>=0;--i){
        for(int j=0;j<26;++j)
            Next[i][j]=Next[i+1][j];
        Next[i][s[i+1]-'a']=i+1;
    }
}
 
int main(){
    scanf("%s",s+1);
    int n=strlen(s+1);
    init(n);
    int q;
    scanf("%d",&q);
    while(q--){
        scanf("%s",t);
        int l=strlen(t);
        int f=1;
        int now=0;
        for(int i=0;i<l;++i){
            now=Next[now][t[i]-'a'];
            if(now==0){
                f=0;
                break;
            }
        }
        printf("%s\n",(f?"YES":"NO"));
    }
    return 0;
}

 

posted @ 2019-09-27 20:54  pengge666  阅读(107)  评论(0编辑  收藏  举报