2019南昌邀请赛网络预选赛 M. Subsequence

•题意

给出一个只包含小写字母的串 s 和n 个串t,判断t[i]是否为串 s 的子序列;

如果是,输出"YES",反之,输出"NO";

•思路

可以把s串中每一个字母的位置预处理出来。(由于总长度是1e5,可能有26个字母,用数组存[26][100000]显然是不可能的,所以就用vector动态分配一下(QwQ)

然后设置一个指针cur,指向当前字母的位置。

再开一个数组记录一下使用后的每个字母的最后一个位置,为了避免每次从第一个开始找。

•代码

#include<bits/stdc++.h>
using namespace std;
const int maxn=100000+5;

vector<int> p[27];
char s[maxn];
char t[maxn];
int a[27];//记录使用后的每个字母的最后一个位置,即这个字母到达的最远的位置
          //后面再找这个字母时,从这个位置的下一个开始找,可以减少查找量

int main()
{
    scanf("%s",s);
    int n=strlen(s);
    for(int i=0;i<n;i++)
        p[s[i]-'a'].push_back(i);//预处理s串每个字母的位置

    int kase;
    scanf("%d",&kase);
    while(kase--)
    {
        memset(a,0,sizeof a);
        int cur=-1;//初始化为-1 因为从0开始
        scanf("%s",t);
        int m=strlen(t);
        int flag;//判断每个字母能不能找到符合要求的
        for(int i=0;i<m;i++)
        {
            flag=0;
            int x=t[i]-'a';
            for(int j=a[x];j<p[x].size();j++)
            {
                if(p[x][j]>cur)//在s串中找x出现的位置 >cur 的第一个位置,有点贪心的感jio
                {
                    cur=p[x][j];//更新cur
                    a[x]=j+1;//记录之前x到达的最远位置j,后面从j+1开始找
                    flag=1;
                    break;
                }
            }
            if(!flag)//没找到需要的字母,肯定t串就不存在
                break;
        }
        if(!flag)
            printf("NO
");
        else
            printf("YES
");
    }
}
View Code
原文地址:https://www.cnblogs.com/MMMinoz/p/11073404.html