HDU 5790 Prefix(字典树、主席树)
来源:互联网 发布:js 鼠标的位置 编辑:程序博客网 时间:2024/06/10 07:21
前置技能
主席树 (模仿kuangbin,不用递归用while)
题目 spoj3290 传送门君
给一串数列,有q个(1e5的数量级)询问,求i到j间的不同数字的个数
题意
N个串,Q个询问。询问第[L,R]的串里面有多少个不同的前缀1<=N<=100000 ,Q<=1e5,串的总长度<=1e5
思路
主席树 + Trie每次插入一个串s[i],相当于新建一棵线段树T[i]。(主席树记录历史状态)。在spoj3290中,T[i]中记录的是[l,r]区间内(1<=l<=r<=i),a[l...r]中不同数字的个数。而这题中,T[i]维护的是,对于字符串数组s[maxn],s[l]...s[r]中有多少不同的前缀。怎样维护的呢?我实现的主席树中,记c[o]为线段树的端点,o是一个区间的编号。这个c[o]维护的是什么呢?若o代表的区间是[j,j],即第j个串(第T[i]个线段树中)。记这些o为o1,o2,....(第1个串,第2个串...)记录的就是这个串s[j]中,最后一次出现的前缀个数。(至于为什么要记录最后一次出现,参考spoj3290的思路)举个栗子(每次插入字符串到Trie中)
第一棵线段树中,Tree[1]的c[o1]+=3
第二棵线段树中, Tree[2]的c[o2]+=2
第三棵线段树问题来了,”abd”的三个前缀都是最后一次出现,所以Tree[3]的c[o3]+=3,但”a”,”ab”在之前的第一棵线段树中已经出现并记录过了,所以要把Tree[3]的c[o1]-=2;
第四棵树,Tree[4]的c[o4]+=4,那么第3棵树中的”ab”与“a”都不是最后一次出现了,Tree[4]的c[o3] -=2。第1棵树中的”abc”也不再是最后一次出现了。所以Tree[4]的c[o1]-=1;第1棵树里也有”ab”,要不要c[o1]再-=2呢?不需要。因为之前插入第3个串的时候,已经减去过了,不必重复再减。
所以说插入一个串i的时候,必然有Tree[i]的c[oi]+=strlen(s[i])
但应该减去Tree[i]的哪些c[o]呢,减去多少呢
所以用一个v[]记录Trie中的每个字符最后一次出现在哪个字符串里。见图。则对于插入的新串中的每个字符ch,那么就让Tree[i]的c[o v[ch] ]–;
例如第4棵树,插入“abce”,插入Trie的时候,第一个a的v为3,那么Tree[4]的c[o3]– 然后v[这个’a’]更新为4。v[‘b’]为3,Tree[4]的c[o3]– 然后v[这个’b’]更新为4。v[‘c’]为1,Tree[4]的c[o1]–; 然后v[这个’c’]更新为4。新建结点e, v[‘e’]就赋值为4
这样查询[L,R]的时候,就对于Tree[R]的c[L..R]求和就行了
坑点
- 用指针实现Trie会MLE,改为数组实现
- 主席树开15 * maxn还是会re ,开30才过(按理说应该开40吧)
代码
#include <vector>#include<cstdio>#include<cstring>#include<algorithm>#include <iostream>#include <stack>#include <cmath>#include <map>#include <set>#include <queue>#include <deque>using namespace std;typedef long long ll;#define MAX 26const int maxn = 1e5+10;const int maxm = 30 * maxn;int N,Q;//-----改掉Trie-----/int nextt[maxn][MAX];int v[maxn];int totTrie;int tot;int a[maxn];int T[maxn], lson[maxm], rson[maxm], c[maxm];int build(int l,int r){ int root = tot ++; c[root] = 0; if(l!=r){ int mid = (l+r) >> 1; lson[root] = build(l,mid); rson[root] = build(mid+1 ,r); } return root;}int Insert(int root,int pos,int val){ int newroot = tot++, tmp = newroot; int l = 1, r = N; c[newroot] = c[root] + val; while( l < r){ int mid = (l + r) >> 1; if(pos <=mid){ lson[newroot] = tot++;rson[newroot] = rson[root]; newroot = lson[newroot]; root = lson[root]; r = mid; }else { rson[newroot] = tot++; lson[newroot] = lson[root]; newroot = rson[newroot]; root = rson[root]; l = mid + 1; } c[newroot] = c[root] +val; } return tmp;}int Query(int root, int p, int l, int r){ if(l == p) return c[root]; int mid = (l+r) >> 1; if( p <= mid) return Query(lson[root], p, l, mid) + c[rson[root]]; return Query(rson[root], p, mid+1, r);}int now;//现在插入的是第几棵树void InsertTrie(){ char ch; int len = 0; int p = 0, q; while((ch=getchar()) != '\n'){ len ++; int id = ch - 'a'; if(nextt[p][id] == -1){ q = ++ totTrie; v[q] = now; memset(nextt[q],-1,sizeof(nextt[q])); nextt[p][id] = q; p = q; } else { p = nextt[p][id]; if(v[p] != 0 ) T[now] = Insert(T[now], v[p], -1); v[p] = now; } } T[now] = Insert(T[now], now, len);}int main() { //freopen("data.in","r",stdin); while( ~scanf("%d",&N)){ getchar(); memset(v,0,sizeof(v)); memset(nextt[0], -1 ,sizeof(nextt[0])); now = totTrie = tot = 0; T[0] = build(1, N); for(int i = 1; i <= N; i++){ ++ now; T[i] = T[i-1]; InsertTrie(); } scanf("%d",&Q); int x,y,z; z=0; while(Q--){ scanf("%d%d",&x,&y); int L,R; L=min( (z+x)%N , (z+y)%N ) +1; R=max( (z+x)%N, (z+y)%N) +1; z=Query(T[R], L, 1, N); printf("%d\n",z); } } return 0;}
- hdu 5790 Prefix(字典树+主席树)
- hdu 5790 Prefix (字典树 + 主席树)
- HDU 5790 Prefix(字典树、主席树)
- hdu 5790 prefix 主席树
- [HDU 5790] Prefix (字符串hash+主席树)
- [HDU5790] Prefix 字典树+主席树
- hdu 5790 Prefix(trie+主席树,好题)
- DNA Prefix (字典树)
- 2016多校第五场 1010 HDU 5790 Prefix 主席树
- hdu 5790 prefix 主席树在线维护区间不同数的个数
- 【主席树】Codechef Prefix XOR
- [主席树] Codechef: Prefix XOR
- DNA Prefix--字典树
- LightOJ 1224 DNA Prefix(字典树)
- light OJ -DNA Prefix (字典树)
- lightOJ 1244 DNA Prefix (字典树)
- hdu5790 Prefix(Trie树+主席树)
- HDU 2665 (主席树)
- Android APP第三方授权登陆,分享等功能合集
- Qt4.8.5移植到嵌入式linux(arm平台)
- BootStrap模态框垂直居中方法
- canvas
- 「Git」合并多个 Commit
- HDU 5790 Prefix(字典树、主席树)
- centos6.4 防火墙管理
- 权限管理命令umask
- 服务端接口测试小结
- c
- 测试面试
- mybatis
- 送机器学习电子书——(TensorFlow)RNN入门
- impdp/expdp导入导出库