牛客 月月查华华手机(枚举优化)
题目传送门
题目分析
1.这个题目如果直接暴力那么时间复杂度太大,那么我们可以用优化方法,直接跳转到后面的字符一一比较,只要有一个不符合,那么就return 0;
2.我们开两个数组,用last数组不断地更新a字符串每个位置的字母,再把它赋给二维数组nec,我们用nec数组来记录每一个字母后面字母出现的相应位置
3.为什么要从后面开始遍历,以为这样非常方便的更新last数组的值,每往前一位,就再次重新赋给当前的nec数组
4.如果匹配的时候,没有与比较字符相同的,那么当前位置所存贮的数就是-1,我们就直接返回0
AC代码
#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;
}
伤害与被伤害,有时候也是对立统一的关系,伤害他人,有时候也意味着毁灭自己。如果我们失去平衡,那么 ——对不起,枪响之后没有赢家 |
---|