由于本蒟蒻刚学算法,所以用了个基础的做法,跑了138ms,内存1892K
之后学习了题解中的方法,内存比第一种方法大十倍,但运行时间短了一点,(数据少的原因吧)
收获颇丰,orz
题意
给定字符串s1,有n次查询,每次查询给出一个字符串s2,问s2是否是s1的子序列。
思路
把s2中的字母按顺序在s1中查询,找到一个后则往后接着找,看能否都找到。
代码
1、暴力
#include<bits/stdc++.h>
using namespace std;
const int maxn=1e6+5;
int n;
char s1[maxn],s2[maxn];
int main(){
scanf("%s",s1);
int len1=strlen(s1);//计算s1的长度
scanf("%d",&n);
while(n--){
scanf("%s",s2);
int j=0;
int len2=strlen(s2);//计算s2的长度
for(int i=0;i<len1;i++){
if(j==len2) break;//s2中的字母全部在s1中找到,结束循环
else if(s1[i]==s2[j]) ++j;//找到一个字母,然后去找下一个
}
if(j==len2) printf("Yes\n");
else printf("No\n");
}
return 0;
}2、枚举优化(刚学了题解中的方法,毕竟我太菜)
#include<bits/stdc++.h>
using namespace std;
const int maxn=1e6+5;
int n,last[30],nex[maxn][30];
char s1[maxn],s2[maxn];
void solve1(){
int len1=strlen(s1);
memset(last,-1,sizeof(last));//-1表示不存在
for(int i=len1-1;i>=0;i--){
for(int j=0;j<26;j++) nex[i][j]=last[j];//将last['a'...'z']复制给当前的next[i]['a'...'z']
last[s1[i]-'a']=i;//当前字母修改last
}
}
bool solve2(){
int len1=strlen(s1),len2=strlen(s2);
int i=last[s2[0]-'a'];//i初值直接赋为A中子串首字母的位置
if(i==-1) return 0;//如果A中没有这个首字母 直接无解
for(int j=1;j<len2;j++){//j遍历子串中的字母(首字母就不必了)
i=nex[i][s2[j]-'a'];//i跳到前一个字母后面的当前字母
if(i==-1) return 0;
}
return 1;
}
int main(){
scanf("%s",s1);
solve1();
scanf("%d",&n);
while(n--){
scanf("%s",s2);
if(solve2()) printf("Yes\n");
else printf("No\n");
}
return 0;
}
京公网安备 11010502036488号