Solution
判断子序列的话让我想起了上次cf的一道C题,哪一场已经忘了,但是做法的话不外乎两种:
1.二分查找
2.序列自动机
因为上次是二分过的,这次就写一下序列自动机。
nexts[i][j]表示的是i位置之后j字符在原串中的索引,那么预处理nexts数组之后,直接对输入的每个串遍历判断 i 位置之后的 s[i] 字符是否存在即可。
最后讲一下预处理,因为是i位置之后的索引,所以要逆序遍历原串,
遍历 j = ' a ' -> ' z ',nexts[i-1][j] = nexts[i][j] ,
特殊地 nexts[ i-1 ][ c[i]-'a' ]=i。

Code

#include<bits/stdc++.h>
#define ll long long
#define fi first
#define se second
#define mp make_pair
#define pb push_back
#define inf 0x3f3f3f3f
using namespace std;
inline ll read(){ll s=0,w=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')w=-1;ch=getchar();}
while(ch>='0'&&ch<='9') s=s*10+ch-'0',ch=getchar();return s*w;}
void put1(){ puts("Yes") ;}void put2(){ puts("No") ;}void put3(){ puts("-1"); }

const int manx=1e6+5;

char s[manx],c[manx];
ll nexts[manx][26];

int main()
{
    cin>> s+1;
    ll n=strlen(s+1);
    for(int i=n;i;i--){
        for(int j=0;j<26;j++)
            nexts[i-1][j]=nexts[i][j];
        nexts[i-1][s[i]-'a']=i;
    }
    ll p=read();
    while(p--){
        cin>>c;
        ll n=strlen(c);
        ll flag=1;
        for(int i=0,now=0;i<n;i++){
            now=nexts[now][c[i]-'a'];
            if(!now){
                flag=0;
                break;
            }
        }
        if(flag) put1();
        else put2();
    }
    return 0;
}