【第0002页 · 枚举】月月查华华的手机

【第0002页 · 枚举】月月查华华的手机

【解题分析】这道题目中需要我们对所有小姐姐的字符串在华华中查找一遍,判断是否是其子串。这里我们首先强调一个概念,在题目中没有说连续子字符串时,所谓的子串是可以不连续的,但是顺序要保持一致。

我们最开始的思路肯定是对每个小姐姐字符串都将华华字符串扫一遍,但此时根据所给数据范围,最坏情况下为 10^12。这是不可以的,因此,我们考虑如何快速地检索字符是本题的关键。

这里,我们给出的思路是:构造一个二维数组用来存储华华的每一位字符之后的下一个字符‘a’,'b','c',...... 分别在什么位置,这样就可以直接跳过中间的其余字符,大大减少检索遍历的次数,从而使最坏情况变为 10^6。这样就符合题目要求了。

有了思路,我们就来写代码了,一些细节部分会在代码中以注释的形式给出,请注意查收哦!

【源码展示】

#include

#include

using namespace std;

const int num = 1e6 + 10;

// nex[][]用来存储每一位字符的下一个字符所在位置

// case[]用来不断刷新下一字符所在位置

int nex[num][30], cast[30];

int main() {

char name[num];

scanf("%s", name);

int len = strlen(name);

// 如果下一个字符,例如'a'不存在了,则它的下一个位置记为-1,表示不存在

memset(cast, -1, sizeof(cast));

// 将每个字符之后的下一个字符的位置存储下来

// 从尾部开始遍历,这样就能确保每次刷新一个字符所在的位置即可

// 但之前需要先把这个位置之后的字符位置存入nex[][]中再刷新cast[]

for (int i = len - 1; i >= 0; i--) {

for (int j = 0; j < 26; j++) {

nex[i][j] = cast[j];

}

cast[name[i] - 'a'] = i;

}

int N;

scanf("%d", &N);

while (N--) {

int flag = 1; // 1表示Yes

char girl[num];

scanf("%s", girl);

int len1 = strlen(girl);

// pos用来记录按照小姐姐字符串的下一位字符在华华字符串中的位置

// 如果出现pos == -1,那么就证明这个小姐姐不是华华的子串

int pos = cast[girl[0] - 'a'];

if (pos == -1) {

printf("No\n");

continue;

}

for (int i = 1; i < len1; i++) {

pos = nex[pos][girl[i] - 'a'];

if (pos == -1) {

flag = 0;

break;

}

}

if (flag == 1) printf("Yes\n");

else printf("No\n");

}

return 0;

}

相关推荐

长虹官方刷机包和刷机教程
365bet体育开户

长虹官方刷机包和刷机教程

📅 07-13 👁️ 4162
同仁堂 国公酒 375ml/瓶
365bet正网盘口

同仁堂 国公酒 375ml/瓶

📅 07-12 👁️ 4508
建行信用卡不激活会影响征信吗?会怎么样?
365bet体育开户

建行信用卡不激活会影响征信吗?会怎么样?

📅 10-14 👁️ 6183