M.Subsequence:
比赛链接:The Preliminary Contest for ICPC China Nanchang National Invitational
题意:给出一个原字符串,给出一个n和n个询问字符串,判断询问字符串是否是原字符串的子串(删除0个或多个字符后,其他字符相对位置保持不变,两字符串相同)。
思路:从后往前记录当前位置之后的所有字母最近的出现的位置,cnt[i][a] = pos, 表示在原字符串当中第 i 个位置之后的所有 ‘ a ’ 中离 i 最近的位置在pos。
反思:最近遇到好多题都是反着记录正着遍历,要在这方面留个心眼。
AC代码:
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
const int maxn = 1e5;
char s[maxn + 5];
int n;
char t[1005];
int cnt[maxn + 5][30];
int main(){
scanf("%s", s + 1);
int n; scanf("%d", &n);
int len = strlen(s + 1);
memset(cnt, -1, sizeof(cnt));
for(int i = len - 1; i >= 1; i--){
for(int j = 'a'; j <= 'z'; j++){
cnt[i][j - 'a'] = cnt[i + 1][j - 'a'];
}
cnt[i][s[i + 1] - 'a'] = i + 1;
}
while(n--){
scanf("%s", t + 1);
int Len = strlen(t + 1);
int flag = -1;
for(int i = 1; i <= len; i++){
if(s[i] == t[1]){
flag = i;
break;
}
}
if(flag == -1) printf("NO\n");
else{
for(int i = 2; i <= Len; i++){
flag = cnt[flag][t[i] - 'a'];
if(flag == -1)break;
}
if(flag == -1) printf("NO\n");
else printf("YES\n");
}
}
return 0;
}