子串查询 二分

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

给出一个长度为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

题意:输入长度为n的字符串s和q个询问 每次询问输入一个字符串t问t是否是s的子串
思路:用二维数组记录所有字母出现的位置 用二分去找一个每次比当前位置大的值,如果不存在比当前位置大的值 则代表子串不存在。

#include <iostream>
#include <algorithm>
#include <vector>

using namespace std;
vector <int> v[30];

int main()
{
    int n,q;
    string t,s;

    cin >> n >> q >> s;

    for(int i=0;i<n;i++)
        v[s[i]-'a'].push_back(i);///记录每个字母出现的各个位置

    while(q--)
    {
        cin >> t;

        int pos=-1;
        bool flag=0;
        vector<int>::iterator it;

        for(int i=0;i<t.size();i++)
        {
             it=upper_bound(v[t[i]-'a'].begin(),v[t[i]-'a'].end(),pos);///寻找当前字母出现的位置

             if(it==v[t[i]-'a'].end())///如果比之前字母出现的位置要大则符合条件 要小即找不到
             {
                 flag=1;
                 break;
             }
             pos=*it;///更新pos的值
        }

        if(flag)
           cout << "NO" << endl;
        else
            cout << "YES" << endl;
    }

    return 0;
}


发布了54 篇原创文章 · 获赞 0 · 访问量 1216

猜你喜欢

转载自blog.csdn.net/weixin_44144278/article/details/100642833