【BZOJ3439】 Kpm的MC密码 (TRIE+主席树)

3439: Kpm的MC密码

Description


 背景

    想Kpm当年为了防止别人随便进入他的MC,给他的PC设了各种奇怪的密码和验证问题(不要问我他是怎么设的。。。),于是乎,他现在理所当然地忘记了密码,只能来解答那些神奇的身份验证问题了。。。

 描述

    Kpm当年设下的问题是这样的:

    现在定义这么一个概念,如果字符串s是字符串c的一个后缀,那么我们称c是s的一个kpm串。

    系统将随机生成n个由a…z组成的字符串,由1…n编号(s1,s2…,sn),然后将它们按序告诉你,接下来会给你n个数字,分别为k1…kn,对于每一个ki,要求你求出列出的n个字符串中所有是si的kpm串的字符串的编号中第ki小的数,如果不存在第ki小的数,则用-1代替。(比如说给出的字符串是cd,abcd,bcd,此时k1=2,那么”cd”的kpm串有”cd”,”abcd”,”bcd”,编号分别为1,2,3其中第2小的编号就是2)(PS:如果你能在相当快的时间里回答完所有n个ki的查询,那么你就可以成功帮kpm进入MC啦~~)

Input

    第一行一个整数 n 表示字符串的数目

    接下来第二行到n+1行总共n行,每行包括一个字符串,第i+1行的字符串表示编号为i的字符串

    接下来包括n行,每行包括一个整数ki,意义如上题所示

Output

    包括n行,第i行包括一个整数,表示所有是si的kpm串的字符串的编号中第ki小的数

Sample Input


3
cd
abcd
bcd
2
3
1

Sample Output

2
-1
2

样例解释

“cd”的kpm 串有”cd”,”abcd”,”bcd”,编号为1,2,3,第2小的编号是

2,”abcd”的kpm串只有一个,所以第3小的编号不存在,”bcd”的kpm

串有”abcd”,”bcd”,第1小的编号就是2。

数据范围与约定

设所有字符串的总长度为len


对于100%的数据,1<=n<=100000,0
 
 
【题意】
  

  给n(10^5)个字符串,总长(10^5),每个字符串给出ki。对于每个字符串si,把每个存在后缀为si的字符串拿出来,其中编号第ki小的就是si的答案。将每个字符串的答案输出。

 

【分析】

  把字符串反过来建一颗字典树,那么它子树上的就都和和他同后缀。求出dfs序,问题就转化成区间第k小的数,用主席树解决。

 

代码如下:

  1 #include<cstdio>
  2 #include<cstdlib>
  3 #include<cstring>
  4 #include<iostream>
  5 #include<algorithm>
  6 #include<queue>
  7 using namespace std;
  8 #define Maxn 100010
  9 #define Maxd 20
 10 
 11 struct node
 12 {
 13     int x,f,p,dfn,rh;
 14     int son[30];
 15 }t[Maxn];
 16 
 17 void upd(int x)
 18 {
 19     t[x].p=0;
 20     memset(t[x].son,0,sizeof(t[x].son));
 21 }
 22 
 23 char s[Maxn];
 24 int n,nt[Maxn],tot;
 25 int wh[Maxn],k[Maxn];
 26 
 27 int mymax(int x,int y) {return x>y?x:y;}
 28 
 29 void init()
 30 {
 31     scanf("%d",&n);
 32     upd(0);tot=0;
 33     for(int i=1;i<=n;i++)
 34     {
 35         scanf("%s",s);
 36         int l=strlen(s);
 37         int now=0;
 38         for(int j=l-1;j>=0;j--)
 39         {
 40             int ind=s[j]-'a'+1;
 41             if(!t[now].son[ind])
 42             {
 43                 t[now].son[ind]=++tot;
 44                 upd(tot);t[tot].f=now;
 45             }
 46             now=t[now].son[ind];
 47             if(j==0)
 48             {
 49                 nt[i]=t[now].p;
 50                 t[now].p=i;
 51                 wh[i]=now;
 52             }
 53         }
 54     }
 55     for(int i=1;i<=n;i++) scanf("%d",&k[i]);
 56 }
 57 
 58 
 59 int cnt,df[Maxn];
 60 void dfs(int x)
 61 {
 62     t[x].dfn=t[x].rh=++cnt;df[cnt]=x;
 63     for(int i=1;i<=26;i++) if(t[x].son[i])
 64     {
 65         dfs(t[x].son[i]);
 66         t[x].rh=t[t[x].son[i]].rh;
 67     }
 68 }
 69 
 70 int rt[Maxn],sum;
 71 struct hp
 72 {
 73     int son[2],cnt;
 74 }a[Maxn*Maxd];
 75 
 76 void dfs2(int l,int x,int dep)
 77 {
 78     if(dep==0) return;
 79     if(a[x].son[0]) dfs2(a[l].son[0],a[x].son[0],dep-1);
 80     else a[x].son[0]=a[l].son[0];
 81     if(a[x].son[1]) dfs2(a[l].son[1],a[x].son[1],dep-1);
 82     else a[x].son[1]=a[l].son[1];
 83 }
 84 
 85 void build()
 86 {
 87     sum=0;
 88     a[0].son[0]=a[0].son[1]=a[0].cnt=0;
 89     rt[0]=0;
 90     for(int i=1;i<=tot;i++)
 91     {
 92         rt[i]=++sum;
 93         int l,r;
 94         l=rt[i-1],r=sum;
 95         a[rt[i]].cnt=a[rt[i-1]].cnt;
 96         for(int j=t[df[i]].p;j;j=nt[j])
 97         {
 98             int x=j;
 99             a[rt[i]].cnt++;
100             l=rt[i-1];r=rt[i];
101             for(int kk=17;kk>=1;kk--)
102             {
103                 int ind=x/(1<<kk-1);
104                 x%=(1<<kk-1);
105                 l=a[l].son[ind];
106                 if(!a[r].son[ind])
107                 {
108                     a[r].son[ind]=++sum;
109                     a[sum].cnt=a[l].cnt;
110                     a[sum].son[0]=a[sum].son[1]=0;
111                 }
112                 r=a[r].son[ind];
113                 a[r].cnt++;
114             }
115         }
116         dfs2(rt[i-1],rt[i],17);
117     }
118 }
119 
120 int ffind(int l,int r,int kk)
121 {
122     l--;
123     l=rt[l];r=rt[r];
124     int ans=0;
125     if(a[r].cnt-a[l].cnt<kk) return -1;
126     for(int i=17;i>=1;i--)
127     {
128         if(a[a[r].son[0]].cnt-a[a[l].son[0]].cnt>=kk)
129         {
130             l=a[l].son[0];
131             r=a[r].son[0];
132         }
133         else
134         {
135             kk-=a[a[r].son[0]].cnt-a[a[l].son[0]].cnt;
136             l=a[l].son[1];
137             r=a[r].son[1];
138             ans+=(1<<i-1);
139         }
140     }
141     return ans;
142 }
143 
144 int main()
145 {
146     init();
147     cnt=-1;
148     dfs(0);
149     build();
150     for(int i=1;i<=n;i++)
151     {
152         printf("%d\n",ffind(t[wh[i]].dfn,t[wh[i]].rh,k[i]));
153     }
154     return 0;
155 }
[BZOJ3439]

 

2016-08-24 11:03:11

posted @ 2016-08-24 10:59  konjak魔芋  阅读(268)  评论(0编辑  收藏  举报