A 子串查询 二分+模拟 看每个子串在主串中是否出现

链接:https://ac.nowcoder.com/acm/contest/28576/A
来源:牛客网

题目描述

给出一个长度为n的字符串s和q个查询。对于每一个查询,会输入一个字符串t,你需要判断这个字符串t是不是s的子串。子串的定义就是存在任意下标a<b<c<d<e,那么”s[a]s[b]s[c]s[d]s[e]”就构成s的一个子串。如”abc”的子串有”a”、”b”、”c”、”ab”、”ac”、”bc”、”abc”。

输入描述:

第一行两个数n,q。1<=n,q<=1e5。

第二行一个长度为n的字符串s,所有字符都为小写拉丁字符。

接下来q行每行一个字符串t。1<=|t|<=50。

输出描述:

对于每个查询,如果t是s的字串,输出”YES”,否则输出”NO”。每个答案占一行。
示例1

输入

复制
8 4
ababcbaa
abac
accb
aaaa
abcba

输出

复制
YES
NO
YES
YES

分析:

将每个数在主串中的位置存下来,在子串中用二分找每个数的位置,如果找不到,就说明NO

//#define int ll
const int N = 2e5+10,P = 131;
int n,m;
string s;
int hasha[N],ba[N];
int p[N];


void solve()
{
    cin>>n>>m;
    cin>>s;
    s = ' ' + s;
    string t;
    V<int> v[27];
    for(int i = 1;i<=n;i++) {
        v[s[i] - 'a'].pb(i);
    }
    for(int i = 0;i < 26;i ++ ) {
        v[i].pb(1e9);
    }
    
    fo(lun,1,m) {
        cin>>t;
        int pos = -1;
        int ok = 1;
        t = ' ' + t;
        for(int i = 1;i<= t.length() - 1; i ++ ) {
            if(v[t[i] - 'a'].size() == 0) {
                ok = 0;break;
            }
            pos = *upper_bound(v[t[i] - 'a'].begin(),v[t[i] - 'a'].end(),pos);
            if(pos == 1e9) {
                ok = 0;break;
            }
        }
        if(ok) {cout<<"YES"<<endl;} else {cout<<"NO"<<endl;}
    }
}

 

 
posted @ 2022-09-15 05:50  er007  阅读(53)  评论(0编辑  收藏  举报