山东济南彤昌机械科技有限公司 山东济南江鹏工贸游有限公司

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编辑  收藏  举报