Subsequence
- 时间:3000ms
- 内存:262144K
Give a string SSS and NNN string TiT_iTi , determine whether TiT_iTi is a subsequence of SSS.
If ti is subsequence of SSS, print YES
,else print NO
.
If there is an array {K1,K2,K3,⋯ ,Km}\lbrace K_1, K_2, K_3,\cdots, K_m \rbrace{K1,K2,K3,⋯,Km} so that 1≤K1<K2<K3<⋯<Km≤N1 \le K_1 < K_2 < K_3 < \cdots < K_m \le N1≤K1<K2<K3<⋯<Km≤N and Ski=TiS_{k_i} = T_iSki=Ti, (1≤i≤m)(1 \le i \le m)(1≤i≤m), then TiT_iTi is a subsequence of SSS.
Input
The first line is one string SSS,length(SSS) ≤100000 \le 100000≤100000
The second line is one positive integer N,N≤100000N,N \le 100000N,N≤100000
Then next nnn lines,every line is a string TiT_iTi, length(TiT_iTi) ≤1000\le 1000≤1000
Output
Print NNN lines. If the iii-th TiT_iTi is subsequence of SSS, print YES
, else print NO
.
样例输入
abcdefg 3 abc adg cba
样例输出
YES YES NO
题目来源:The Preliminary Contest for ICPC China Nanchang National Invitational and International Silk-Road Programming Contest
-
大意:给出一个字符串S和N个字符串Ti,问这N个字符串是否为S的子串(不一定连续)。
-
分析:由于N很大,不能暴力。因此可以记录下26个英文字母在主串中出现的位置。设当前Ti中的字符在主串中的最大位置为-1,遍历Ti,对于每一个字符,在主串中找到一个比当前最大位置大的位置:
若找到了,更新当前最大位置 否则,说明Ti不是S的子串
若一直到最后都可以更新最大位置,说明Ti是S的子串。
AC代码:
#include <iostream>
#include <cstdio>
#include <vector>
#include <cstring>
using namespace std;
const int maxn = 100005;
//字母出现位置邻接表
vector<vector<int> > vst(26);
int st[26];//未匹配的位置的起点
char s[maxn],ti[maxn];
int main()
{
scanf("%s",s);
int s_len = strlen(s);
for(int i = 0; i < s_len; ++i)
vst[s[i]-'a'].push_back(i);
int n;
scanf("%d",&n);
for(int i = 0; i < n; ++i)
{
for(int j = 0; j < 26; ++j) st[j]=0;
scanf("%s",ti);
int t_len = strlen(ti);
//已匹配的最大位置
int maxloc=-1;
int flag=1;
for(int j = 0; j < t_len; ++j)
{
int zm = ti[j]-'a';
if(st[zm]>=vst[zm].size())
{
flag=0;
break;
}
flag=0;
for(int k = st[zm]; k <vst[zm].size(); ++k)
{
if(vst[zm][k]>maxloc)
{
maxloc=vst[zm][k];
st[zm]=k+1;
flag=1;
break;
}
}
if(flag==0)
break;
}
printf("%s\n",flag?"YES":"NO");
}
return 0;
}