Nowcoder contest 392 J (模板题)【序列自动机】

<题目链接>

题目大意:
给你一个母串A,然后进行q次询问,每次询问给定一个长度不超过母串的字符串,问你这个字符串是否是母串的子串。

解题分析:
本题的思想就是考虑贪心的去匹配,我们希望当前匹配到的位置越靠前越好。所以对于母串每一位都记一下下一次出现某个字符的位置。匹配的时候从第零位(虚根)开始,如果能一直匹配下去就是$Yes$ ,否则就是 $No$,这些操作就是用序列自动机简单实现。

单次查询的复杂度是$O(|B_i|)$ 的,序列自动机预处理的复杂度是 $O(26|A|)$的。总时间复杂度是$O(26|A|+\sum_{i=1}^N |B_i|)$。

#include<bits/stdc++.h>
using namespace std;

const int N = 1e6+5;
int n,m,T;
char str[N],s[N];
int nxt[N][26],pos[26];
 
void init(){     //预处理主串的信息
    n=strlen(str+1);
    for(int i=0;i<26;i++) pos[i]=n+1;    //a~z中每个字母的下一个字母所对应的位置
    for(int i=n;~i;i--){
        for(int j=0;j<26;j++)
            nxt[i][j]=pos[j]; //记录下下一次出现这个字符的位置
        pos[str[i]-'a']=i;    //更新a[i]最对应的字母对应的当前最靠前的位置
    }
}
bool solve(){
    scanf("%s",s+1);
    m=strlen(s+1);int x=0;   //x从0开始,0作为虚根
    for(int i=1;i<=m;i++){
        int v=s[i]-'a';
        if(nxt[x][v]==n+1) return false;    //如果下一个出现字符的位置不存在,则说明该子串并未完全匹配
        x=nxt[x][v];
    } return true;
}
 
int main(){
    scanf("%s",str+1);
    cin>>T;init();
    while(T--) solve()?puts("Yes"):puts("No");
}

猜你喜欢

转载自www.cnblogs.com/00isok/p/10503988.html