月月查华华的手机
月月查华华的手机
https://ac.nowcoder.com/acm/problem/23053
题目分析
1.这个题目如果直接暴力那么时间复杂度太大,那么我们可以用优化方法,直接跳转到后面的字符一一比较,只要有一个不符合,那么就return 0;
2.我们开两个数组,用last数组不断地更新a字符串每个位置的字母,再把它赋给二维数组nec,我们用nec数组来记录每一个字母后面字母出现的相应位置
3.为什么要从后面开始遍历,以为这样非常方便的更新last数组的值,每往前一位,就再次重新赋给当前的nec数组
4.如果匹配的时候,没有与比较字符相同的,那么当前位置所存贮的数就是-1,我们就直接返回0
#include <bits/stdc++.h> using namespace std; const int maxn = 1e6 + 10; char a[maxn], b[maxn]; int n, last[30], nec[maxn][30]; void deal() { memset(last, -1, sizeof(last)); //初始化标记 int la = strlen(a); for (int i = la - 1; i >= 0; --i) //从后往前遍历,方便填数 { for (int k = 0; k < 26; ++k) nec[i][k] = last[k]; //赋值给当前的nec数组 last[a[i] - 'a'] = i; //用当前字母修改last } } bool judge() { int la = strlen(a); int lb = strlen(b); int i = last[b[0] - 'a']; //i初值直接赋为A中子串首字母的位置 if (i == -1) return 0; //如果A中没有这个首字母 直接无解 for (int j = 1; j < lb; ++j) //从第二个字母开始遍历因为首字母已经完成了赋值与判断 { i = nec[i][b[j] - 'a']; //直接跳转 if (i == -1) return 0; } return 1; } int main() { scanf("%s", a); deal(); scanf("%d", &n); for (int i = 1; i <= n; ++i) { scanf("%s", b); if (judge()) printf("Yes\n"); else printf("No\n"); } return 0; }