思路:1.不要让之前做过的工作作废(来回反复找)2.提前记录好,让后面的输入只是在查询 3.子序列可以不连续,但相对顺序不能改变

AC代码&思路:

#include<iostream>
#include<string>//string类型
#include<cstring>//memset()
using namespace std;
int nxt[1000005][30];//next会重名 reference to 'next' is ambiguous
int cur[30];//26个字母,开30保险一点
int main()
{
    ios::sync_with_stdio(false);cin.tie(nullptr);
    string s;int q;
    cin>>s;cin>>q;
    int len=s.length();
    memset(cur,-1,sizeof(cur) );//初始值赋为-1,一个不可能取到的值,即代表不存在
    for(int i=len-1;i>=0;i--)//算出原字符串每一个字母下一个26个字母分别所在的第一个位置,这样就不需要一直找下去了
    {
        for(int j=0;j<26;j++)//遍历26个字母
        {
            nxt[i][j]=cur[j];//cur[j]代表某个字母在当前字母后面的第一个位置
        }
        cur[s[i]-'a']=i;//这里要放在前面那个变量26个字母的循环后面,因为如果放在它前面,就不是next字母了,而是把当前的那个字母也算进去了,相当于算了两遍当前子母
    }
    string t;int tlen;bool flag;
    for(int k=0;k<q;k++)
    {  
        flag=1;
        cin>>t;tlen=t.length();
        int pos=cur[t[0]-'a'];//发现上面那个循环cur每个元素最后一次计算的结果刚好就是这个元素第一次出现的位置,这不也体现了倒着遍历的优越性吗?
        if (pos==-1){cout<<"No\n";continue;}//万一第一个字符就没找到呢,还是保险点比较好
        for(int i=1;i<tlen;i++)
        {
            pos=nxt[pos][t[i]-'a'];//让pos直接跳到下一个字母出现的位置来找字符串当前这个字符第一次出现的位置,不用再一个一个检索了,大大降低时间复杂程度
          //不要忘了写“-'a'”!!!!!!
            if(pos==-1){flag=0;cout<<"No\n";break;}
        }
        if(flag==1){cout<<"Yes\n";}
    }
    return 0;
}

注:为什么要反着检索?因为要找离某个字符自己最近的下一个26个字符,正向查找是离你越来越远。反向查找是离你越来越近,具有天生的优势。这道题当然也可以用正向查找,但又要增加一个数组检测当前字母是否已经被查找过,查找过就continue;这样明显增加了算法的复杂程度