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

本来想找\(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;
    }
}

转载于:https://www.cnblogs.com/maomao9173/p/10441309.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值