牛客小白月赛12J-月月查华华的手机-(思维)

https://ac.nowcoder.com/acm/contest/392/J

题意:判断一个子串是不是母串的子序列。len<=1e6。

思路:子序列不要求连续,可以跳跃性地寻找,例如abcdefg,查找ag,找到a不需要找bcdef,直接找g是否存在。对于当前字符,记录 下一个特定字符 在第一次出现时的下标,这样就可以将子序列连接起来,打表从后往前。

#include<stdio.h>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<math.h>
#include<string>
#include<map>
#include<queue>
#include<stack>
#include<set>
#define ll long long
#define inf 0x3f3f3f3f
using namespace std;

char a[1000086];
char b[1000086];
int next1[1000086][26];
int nextt[30];///下一个指定字符的位置
int n,m;

void init()///初始化打表
{
    for(int i=n;i>=1;i--)
    {
        for(int j=0;j<26;j++)
            next1[i][j]=nextt[j];
        int x=a[i]-'a';
        nextt[x]=i;
    }
}

bool check()
{
    int len=strlen(b+1);
    if(len==1)
    {
        if(nextt[ b[1]-'a' ]!=0)
            return true;
        else
            return false;
    }
    int now=2;
    int i=nextt[ b[1]-'a' ];///第一个字母在原串之中的位置
    int j=b[now]-'a';
    while(i!=0 && next1[i][j]!=0)
    {
        i=next1[i][j];///i跳到那一步取
        now++;
        if(now>len)
            return true;
        if(now)
        j=b[now]-'a';
    }
    return false;

}

int main()
{
    scanf("%s",a+1);
    n=strlen(a+1);
    init();
    scanf("%d",&m);
    while(m--)
    {
        scanf("%s",b+1);
        if(check())
            printf("Yes\n");
        else
            printf("No\n");
    }
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/shoulinniao/p/12654211.html