zoukankan      html  css  js  c++  java
  • 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
    ", 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
    ", now, sum[now], sz[now]);
    		now = ch[now][s[i]];
    		ans += sum[now];
    	}
    	// printf ("now = %d
    ", 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;
    	}
    }
    
    
  • 相关阅读:
    2333
    STL string
    后缀自动机的应用
    省选一轮
    等价类计数问题(Polya定理和burnside引理)
    Prufer序列与树的计数(坑)
    分治算法
    生成函数
    莫队算法
    Xamarin 技术解析
  • 原文地址:https://www.cnblogs.com/maomao9173/p/10441309.html
Copyright © 2011-2022 走看看