bzoj 3439 Kpm的MC密码(Trie+dfs序+主席树)
【题目链接】
http://www.lydsy.com/JudgeOnline/problem.php?id=3439
【题意】
给定若干串,问一个串的作为其后缀的给定串集合中的第k小。
【思路】
如果将每个串反向,则问题为一个串作为其前缀的给定串集合的第k小。
如果用Trie组织数据,则发现该串对应的集合即为以Trie上以尾节点为根的子树。我们按照dfs序构造序列,则问题即为连续区间上的第k大,可以用主席树求出。
注意有重复的串。
【代码】
1 #include<set> 2 #include<cmath> 3 #include<queue> 4 #include<vector> 5 #include<cstdio> 6 #include<cstring> 7 #include<iostream> 8 #include<algorithm> 9 #define trav(u,i) for(int i=front[u];i;i=e[i].nxt) 10 #define FOR(a,b,c) for(int a=(b);a<=(c);a++) 11 using namespace std; 12 13 typedef long long ll; 14 const int N = 1e6+100; 15 16 ll read() { 17 char c=getchar(); 18 ll f=1,x=0; 19 while(!isdigit(c)) { 20 if(c=='-') f=-1; c=getchar(); 21 } 22 while(isdigit(c)) 23 x=x*10+c-'0',c=getchar(); 24 return x*f; 25 } 26 27 char s[N]; 28 int n,m,dfsc,L[N],R[N],dfs_list[N],sz; 29 30 struct Trie { 31 int ch[N][26],sz; 32 vector<int> num[N]; 33 Trie() { 34 sz=0; 35 memset(ch,0,sizeof(ch)); 36 } 37 void insert(char *s,int val) { 38 int u=0; 39 for(int i=0;s[i];i++) { 40 int c=s[i]-'a'; 41 if(!ch[u][c]) ch[u][c]=++sz; 42 u=ch[u][c]; 43 } 44 num[u].push_back(val); 45 } 46 void dfs(int u) 47 { 48 int tmp=dfsc+1; 49 FOR(i,0,(int)num[u].size()-1) { 50 dfs_list[++dfsc]=num[u][i]; 51 L[num[u][i]]=tmp; 52 } 53 FOR(c,0,25) if(ch[u][c]) 54 dfs(ch[u][c]); 55 FOR(i,0,(int)num[u].size()-1) 56 R[num[u][i]]=dfsc; 57 } 58 } trie; 59 60 struct Tnode { 61 Tnode *ch[2]; 62 int num; 63 void * operator 64 new(size_t size,Tnode *l,Tnode *r,int x) ; 65 }*T[N],*mempool,*G; 66 //´óСΪ 1<<15 µÄÄÚ´æ³Ø 67 void *Tnode::operator new (size_t size,Tnode *l,Tnode*r,int x) { 68 if(G==mempool) { 69 G=new Tnode[1<<15]; 70 mempool=G+(1<<15); 71 memset(G,0,sizeof(Tnode)*(1<<15)); 72 } 73 G->ch[0]=l,G->ch[1]=r,G->num=x; 74 return G++; 75 } 76 77 Tnode* build(Tnode* p,int l,int r,int val) { 78 int mid=l+r>>1; 79 if(l==r) return new (0x0,0x0,p->num+1)Tnode; 80 if(val<=mid) 81 return new (build(p->ch[0],l,mid,val),p->ch[1],p->num+1)Tnode; 82 else 83 return new (p->ch[0],build(p->ch[1],mid+1,r,val),p->num+1)Tnode; 84 } 85 int query(Tnode *x,Tnode *y,int l,int r,int rk) { 86 int mid=l+r>>1; 87 if(l==r) return mid; 88 int sum=y->ch[0]->num - x->ch[0]->num; 89 if(rk<=sum) return query(x->ch[0],y->ch[0],l,mid,rk); 90 else return query(x->ch[1],y->ch[1],mid+1,r,rk-sum); 91 } 92 93 int main() 94 { 95 n=read(); 96 FOR(i,1,n) { 97 scanf("%s",s); 98 int n=strlen(s); 99 for(int j=0;j*2<n;j++) 100 swap(s[j],s[n-1-j]); 101 trie.insert(s,i); 102 } 103 trie.dfs(0); 104 105 T[0]=new (0x0,0x0,0) Tnode; 106 T[0]->ch[0]=T[0]->ch[1]=T[0]; 107 108 FOR(i,1,n) 109 T[i]=build(T[i-1],1,n,dfs_list[i]); 110 FOR(i,1,n) { 111 int k=read(); 112 if(k>R[i]-L[i]+1) puts("-1"); 113 else printf("%d\n",query(T[L[i]-1],T[R[i]],1,n,k)); 114 } 115 return 0; 116 }
posted on 2016-03-28 15:08 hahalidaxin 阅读(263) 评论(0) 编辑 收藏 举报