【每日一题】月月查华华的手机题解
月月查华华的手机
https://ac.nowcoder.com/acm/problem/23053
对所有需要查询的字符串建立字典树,通过对字符串A的扫描在字典树上做遍历,确定所有可以到达的字典树节点从而确定答案。
扫描方法为先初始化只需要一个字母就能到达的节点(即字典树的根的所有子节点),然后对每一个字母找到所有可以到达的节点,再更新差一步到达的节点。
#include <bits/stdc++.h> typedef long long ll; using namespace std; const int p = 1000000007; struct Node { vector<int> id;// 可能有相同的待查询字符串 Node* c[26]; Node() { for (int i = 0; i < 26; ++i) c[i] = NULL; } }; Node* root = new Node; char a[1001000], b[1001000]; vector<Node*> v[26]; bool ans[1001000]; void solve() { for (int i = 0; i < 26; ++i) if (root->c[i] != NULL) v[i].push_back(root->c[i]);// 初始化差一个字母就能到达的位置 int len = strlen(a); for (int i = 0; i < len; ++i) if (v[a[i] - 'a'].empty() == false) { vector<Node*> tmp = v[a[i] - 'a']; v[a[i] - 'a'].clear(); for (int j = 0; j < tmp.size(); ++j) {// 已经到达的位置 for (auto k = tmp[j]->id.begin(); k < tmp[j]->id.end(); ++k) { ans[*k] = true; } for (int k = 0; k < 26; ++k)// 添加差一个字母就能到达的位置 if (tmp[j]->c[k] != NULL) v[k].push_back(tmp[j]->c[k]); } } } int n; int main() { scanf("%s", a); scanf("%d", &n); for (int i = 0; i < n; ++i) { scanf("%s", b); int len = strlen(b); Node* r = root;// 建字典树 for (int j = 0; j < len; ++j) { if (r->c[b[j] - 'a'] == NULL) r->c[b[j] - 'a'] = new Node; r = r->c[b[j] - 'a']; } r->id.push_back(i); } solve(); for (int i = 0; i < n; ++i) if (ans[i]) printf("Yes\n"); else printf("No\n"); return 0; }