【每日一题】月月查华华的手机题解

月月查华华的手机

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;
}
全部评论

相关推荐

点赞 收藏 评论
分享
牛客网
牛客企业服务