[BZOJ3439]Kpm的MC密码
题目大意:
给定$n(n\leq10^5)$个字符串$s_{1\sim n}$,$n$次询问,每次询问所有满足$s_i$是$t$的后缀的$t$中,编号第$k_i$小的$t$的编号。
思路:
倒着建字典树,根据DFS序建立主席树,维护每个区间内编号出现次数。
1 #include<list> 2 #include<cstdio> 3 #include<cctype> 4 #include<cstring> 5 #include<algorithm> 6 inline int getint() { 7 register char ch; 8 while(!isdigit(ch=getchar())); 9 register int x=ch^'0'; 10 while(isdigit(ch=getchar())) x=(((x<<2)+x)<<1)+(ch^'0'); 11 return x; 12 } 13 const int N=100001,logN=18,S=26; 14 int n; 15 class FotileTree { 16 private: 17 struct Node { 18 int val,left,right,vis; 19 }; 20 Node node[N*logN]; 21 int sz,new_node(const int &p,const int &id) { 22 node[++sz]=node[p]; 23 node[sz].vis=id; 24 return sz; 25 } 26 public: 27 int root[N]; 28 void modify(int &p,const int &b,const int &e,const int &x,const int &y,const int &id) { 29 if(node[p].vis!=id) p=new_node(p,id); 30 node[p].val+=y; 31 if(b==e) return; 32 const int mid=(b+e)>>1; 33 if(x<=mid) modify(node[p].left,b,mid,x,y,id); 34 if(x>mid) modify(node[p].right,mid+1,e,x,y,id); 35 } 36 int query(const int &p,const int &q,const int &b,const int &e,const int &k) { 37 if(node[q].val-node[p].val<k) return -1; 38 if(b==e) return b; 39 const int mid=(b+e)>>1; 40 if(node[node[q].left].val-node[node[p].left].val>=k) return query(node[p].left,node[q].left,b,mid,k); 41 return query(node[p].right,node[q].right,mid+1,e,k-(node[node[q].left].val-node[node[p].left].val)); 42 } 43 }; 44 FotileTree t; 45 class Trie { 46 private: 47 int pos[N],ch[N][S],par[N],dfn[N],size[N],cnt; 48 std::list<int> val[N]; 49 int sz,new_node(const int &p) { 50 par[++sz]=p; 51 return sz; 52 } 53 int idx(const char &c) const { 54 return c-'a'; 55 } 56 void push_up(const int &p) { 57 size[p]=1; 58 for(register int i=0;i<S;i++) size[p]+=size[ch[p][i]]; 59 } 60 public: 61 void insert(const char s[],const int &id) { 62 int u=0; 63 for(register int i=0;s[i];i++) { 64 u=ch[u][idx(s[i])]=ch[u][idx(s[i])]?:new_node(u); 65 } 66 val[pos[id]=u].push_back(id); 67 for(;u;u=par[u]) push_up(u); 68 } 69 void dfs(const int &x) { 70 dfn[x]=cnt++; 71 if(dfn[x]) t.root[dfn[x]]=t.root[dfn[x]-1]; 72 for(register std::list<int>::iterator i=val[x].begin();i!=val[x].end();i++) { 73 t.modify(t.root[dfn[x]],1,n,*i,1,dfn[x]); 74 } 75 for(int i=0;i<S;i++) { 76 if(ch[x][i]) dfs(ch[x][i]); 77 } 78 } 79 int query(const int &id,const int &k) { 80 return t.query(t.root[dfn[pos[id]]-1],t.root[dfn[pos[id]]+size[pos[id]]-1],1,n,k); 81 } 82 }; 83 Trie trie; 84 char s[N]; 85 int main() { 86 n=getint(); 87 for(register int i=1;i<=n;i++) { 88 scanf("%s",s); 89 std::reverse(&s[0],&s[strlen(s)]); 90 trie.insert(s,i); 91 } 92 trie.dfs(0); 93 for(register int i=1;i<=n;i++) { 94 printf("%d\n",trie.query(i,getint())); 95 } 96 return 0; 97 }