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;
}
京公网安备 11010502036488号