首页 > 其他 > 详细

Luogu P2922 [USACO08DEC]秘密消息Secret Message 字典树 Trie树

时间:2019-02-27 10:09:05      阅读:156      评论:0      收藏:0      [点我收藏+]

本来想找\(01Trie\)的结果找到了一堆字典树水题。。。算了算了当水个提交量好了。

直接插入模式串,维护一个\(Trie\)树的子树\(sum\)大小,求解每一个文本串匹配时走过的链上匹配数和终点处的子树大小之和。

#include <bits/stdc++.h>
using namespace std;

int top, sta[10010];
int n, m, l, s[10010], max_size;
int ch[500010][2], sz[500010], sum[500010];

void push_up (int p) {
    sz[p] = sum[p];
    if (ch[p][0]) sz[p] += sz[ch[p][0]];
    if (ch[p][1]) sz[p] += sz[ch[p][1]];
}

void add_str () {
    int now = 0;
    sta[top = 1] = 0;
    for (int i = 1; i <= l; ++i) {
        if (!ch[now][s[i]]) {
            ch[now][s[i]] = ++max_size;
        }
        // printf ("ch[%d][%d] = %d\n", now, s[i], ch[now][s[i]]);
        now = ch[now][s[i]];
        sta[++top] = now;
    }
    sz[now]++;
    sum[now]++;
    while (top > 0) push_up (sta[top--]);
}

int get_str () {
    int now = 0, ans = 0;
    for (int i = 1; i <= l; ++i) {
        if (!ch[now][s[i]]) {
            return ans;
        }
        // printf ("now = %d, sum[now] = %d sz[now] = %d\n", now, sum[now], sz[now]);
        now = ch[now][s[i]];
        ans += sum[now];
    }
    // printf ("now = %d\n", now);
    ans += sz[now] - sum[now];
    return ans;
}

int main () {
    cin >> m >> n;
    for (int i = 1; i <= m; ++i) {
        scanf ("%d", &l);
        for (int j = 1; j <= l; ++j) {
            scanf ("%d", &s[j]);
        }
        add_str ();
    }
    for (int i = 1; i <= n; ++i) {
        scanf ("%d", &l);
        for (int j = 1; j <= l; ++j) {
            scanf ("%d", &s[j]);
        }
        cout << get_str () << endl;
    }
}

Luogu P2922 [USACO08DEC]秘密消息Secret Message 字典树 Trie树

原文:https://www.cnblogs.com/maomao9173/p/10441309.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!