【HDU - 5790 】Prefix(主席树+Trie树)
2017-06-28 22:07
435 查看
BUPT2017 wintertraining(15) #7C
读入每个字符串后,用Trie树给它的每个前缀分配ID,并记录每个前缀最后出现的位置pre[cur],如果当前的前缀出现过,则线段树中上一次出现的位置的值-1,相当于只把这种前缀记录在最后出现的位置上。然后当前位置(第几个字符串)贡献了字符串长度个前缀。
那么求[L,R]就相当于求前R个字符串对应的线段树的区间[L,n]的值,因为这样肯定不会包含只在R后面出现的前缀,而前R个字符串对应的线段树(主席树就相当于n个线段树),每个前缀只在最后出现的位置上有贡献,于是它[L,n]一定包含所有这个区间出现的前缀。
题意
求[min((Z+L)%N,(Z+R)%N)+1,max((Z+L)%N,(Z+R)%N)+1]中不同前缀的个数,Z是上次询问的结果,N是字符串总个数。Q次询问。题解
用主席树,即函数式线段树,维护前i个字符串的区间和(每个区间的前缀个数之和)。读入每个字符串后,用Trie树给它的每个前缀分配ID,并记录每个前缀最后出现的位置pre[cur],如果当前的前缀出现过,则线段树中上一次出现的位置的值-1,相当于只把这种前缀记录在最后出现的位置上。然后当前位置(第几个字符串)贡献了字符串长度个前缀。
那么求[L,R]就相当于求前R个字符串对应的线段树的区间[L,n]的值,因为这样肯定不会包含只在R后面出现的前缀,而前R个字符串对应的线段树(主席树就相当于n个线段树),每个前缀只在最后出现的位置上有贡献,于是它[L,n]一定包含所有这个区间出现的前缀。
代码
#include <cstdio> #include <iostream> #include <cstring> #include <string> #include <algorithm> const int N=100005; const int M=N*40; using namespace std; namespace PST{ int T ,lson[M],rson[M],tot,c[M],n; void init(int _n){ tot=0; n=_n; memset(c,0,sizeof c); } int build(int l,int r){ ++tot; c[tot]=0; if(l<r){ int mid=l+r>>1; lson[tot]=build(l,mid); rson[tot]=build(mid+1,r); } return tot; } int update(int root,int pos,int val){ int newroot=++tot, tmp=tot; c[tmp]=c[root]+val; int l=1,r=n; while(l<r){ int mid=l+r>>1; if(pos<=mid){ lson[newroot]=++tot; rson[newroot]=rson[root]; root=lson[root]; r=mid; } else{ rson[newroot]=++tot; lson[newroot]=lson[root]; root=rson[root]; l=mid+1; } newroot = tot; c[newroot] = c[root] + val; } return tmp; } int query(int root,int pos){ int ret=0; int l=1,r=n; while(l<pos){ int mid=l+r>>1; if(pos<=mid){ ret+=c[rson[root]]; r=mid; root=lson[root]; } else{ l=mid+1; root=rson[root]; } } return c[root]+ret; } } namespace Trie{ int node [27]; int tot, pre ; void Insert(string& s,int x){ int cur=0; for(int i=0;i<s.size();++i){ int p=s[i]-'a'; if(node[cur][p]==0) node[cur][p]=++tot; cur=node[cur][p]; if(pre[cur]){ PST::T[x]=PST::update(PST::T[x], pre[cur], -1); } pre[cur]=x+1; } } void init(){ tot=0; memset(node,0,sizeof node); memset(pre,0,sizeof pre); } } string s; int main(){ int n; while(~scanf("%d",&n)){ int z=0; Trie::init(); PST::init(n); PST::T[0]=PST::build(1,n); for(int i=0;i<n;++i){ if(i)PST::T[i]=PST::T[i-1]; cin>>s; Trie::Insert(s, i); PST::T[i]=PST::update(PST::T[i], i+1, s.size()); } int q; scanf("%d",&q); while(q--){ int l,r; scanf("%d%d",&l,&r); l=(l+z)%n,r=(r+z)%n; if(r<l)swap(l,r); z=PST::query(PST::T[r],l+1); printf("%d\n",z); } } return 0; }
相关文章推荐
- hdu 5790 Prefix(字典树+主席树)
- HDU 5790 Prefix(字典树、主席树)
- hdu 5790 prefix 主席树在线维护区间不同数的个数
- hdu 5790 Prefix (字典树 + 主席树)
- hdu 5790 prefix 主席树
- hdu_5790_Prefix(trie+主席树)
- [HDU 5790] Prefix (字符串hash+主席树)
- 2016多校第五场 1010 HDU 5790 Prefix 主席树
- hdu 5790 Prefix(trie+主席树,好题)
- hdu5790 Prefix(2016多校第五场1009)trie+主席树
- hdu5790 Prefix(Trie树+主席树)
- HDU 11488 Hyper Prefix Sets (字符串-Trie树)
- HDU 11488 Hyper Prefix Sets (字符串-Trie树)
- 【HUD-5790】Prefix (主席树+tire)
- Hdu 5790 Prefix(每次查询问你第L个字符串和第R个字符串之间的公共前缀有多少个)
- HDU-5790 Tire树+主席树
- HDU 11488 Hyper Prefix Sets (字符串-Trie树)
- HDU 1247-Hat’s Words(trie树)
- hdu 1800 trie树
- hdu 1247 Hat’s Words Trie树