子串查询
链接: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
分析:一个字符串查询一次时间复杂度无疑很高,肯定会超时,增加标志位,每个字母都标出下一个字母的位置,子串查询的时候直接查询下一个字母的下标,省去了遍历的过程,只遍历一次原数组增加标志位
完整代码:
#include<iostream>
#include<vector>
#include<string>
#include <algorithm>
using namespace std;
vector<long long > vec;
string s;
int p,q;
int main(){
vector<int > vec[27]; //存放标志位
string str;
int len;
cin>>p>>q;
cin>>s;
for(int i=0,len=s.length();i<len;i++) vec[s[i]-'a'].push_back(i);
while(q--){
cin>>str;
int flag=0;
int pos=-1;
for(int k=0,n=str.length();k<n;k++){
vector<int>::iterator it =upper_bound(vec[str[k]-'a'].begin(),vec[str[k]-'a'].end(),pos);
if(it==vec[str[k]-'a'].end()){
flag=1;
break;
}
pos=*it;
}
if(flag)
cout<<"NO"<<endl;
else
cout<<"YES"<<endl;
}
}