4.2 每日一题题解

月月查华华的手机

涉及知识点:

  • 预处理/字符串匹配

solution:

  • 这是牛客今天的每日一题,大家可以写题解领取牛币(牛币可以兑换卫衣,抱枕!)戳这里进入活动页面
  • 题意:给出母串 s,给出 m 次询问,每次询问给出的子串 si 是否是 s 的子序列
  • 字符串s的长度为1e6,给出的子串si的长度总和也为1e6,如果n方暴力枚举一定会超时
  • 所以我们可以对字符串s做一下处理
  • 设nex[ i ][ 'a' - 'z' ] 表示第 i 个位置的字母后第一个 'a' - 'z' 字母的位置,提前预处理母串s,查询子串 si 就可以简化到O( n )
  • 这样我们遍历子串si,实际上就相当于在母串s上不断地跳跃(不懂的可以结合代码模拟一下),如果遍历完子串si,说明si 是 s 的子序列,否则不是

std:

#include <bits/stdc++.h>
using namespace std;
#define ll long long
const int maxn = 1e6 + 5;
char s[maxn];
int nex[maxn][26];
int main()
{
    scanf("%s",s+1);
    int l = strlen(s+1);
    for(int i=l-1;i>=0;i--)
    {
        for(int j=0;j<26;j++)
        {
            nex[i][j] = nex[i+1][j];
        }
        nex[i][s[i+1]-'a'] = i+1;
    }
    int t;
    scanf("%d",&t);
    while(t--)
    {
        scanf("%s",s+1);
        l = strlen(s+1);
        int k = 0,flag = 0;
        for(int i=1;i<=l;i++)
        {
            if(nex[k][s[i]-'a'])
                k = nex[k][s[i]-'a'];
            else{
                flag = 1;
                break ;
            }
        }
        if(flag)
            printf("No\n");
        else
            printf("Yes\n");
    }
    return 0;
}

posted @ 2020-04-02 14:23  QFNU-ACM  阅读(93)  评论(0编辑  收藏  举报