<题目链接>
题目大意:
给你一个母串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"); }
原文地址:https://www.cnblogs.com/00isok/p/10503988.html
时间: 2024-10-08 05:12:29