链接: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
题意:问你一个字符串是不是另一个字符串的子串
思路:对每个字母,纪录它在字符串的所有位置,这样,你在判断一个字符串的t的时候,从第i字母找离i-1个字母最近的位置,如果找不到则输出no,所有字母都找的到输出YES
#include<stdio.h>
#include<math.h>
#include<vector>
#include<cstring>
#include<iostream>
#include<algorithm>
#define maxn 205000
using namespace std;
#define ll long long
int id[30],num[30][maxn];char a[maxn],b[105];
void init()
{
memset(num,0x3f,sizeof(num));
memset(id,0,sizeof(id));
}
int main()
{
int n,q;
scanf("%d %d",&n,&q);
scanf(" %s",a+1);
init();
for(int i=1;i<=n;i++)
{
int x=a[i]-'a'+1;
num[x][++id[x]]=i;
}
/*for(int i=1;i<=26;i++)
{
if(id[i]==0) continue;
printf("i=%c: ",i+'a'-1);
for(int j=1;j<=id[i];j++)
{
printf("%d ",num[i][j]);
}
printf("\n");
}*/
while(q--)
{
scanf(" %s",b+1);
int x=0;int f=1;
for(int i=1;b[i]!='\0';i++)
{
int p=b[i]-'a'+1;
if(id[p]==0)
{
f=0;
break;
}
int y=*upper_bound(num[p]+1,num[p]+id[p]+1,x);
int y1=upper_bound(num[p]+1,num[p]+id[p]+1,x)-num[p];
//printf("b[%d]=%c y=%d\n",i,b[i],y);
if(y<=x||y1>id[p])
{
f=0;
break;
}
x=y;
}
if(f==0) printf("NO\n");
else printf("YES\n");
}
}