bzoj3439 Kpm的MC密码
2017-06-11 21:52
405 查看
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
3cd
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
正解:$trie$树套权值线段树。
比较简单的数据结构板子题。我们把每个串倒过来然后加到$trie$树中,每经过$trie$树上一个结点就在当前点对应的权值线段树中加入编号。查询的时候直接找以当前串为前缀的所有字符串的编号$k$小值就行了。
//It is made by wfj_2048~ #include <algorithm> #include <iostream> #include <cstring> #include <cstdlib> #include <cstdio> #include <vector> #include <cmath> #include <queue> #include <stack> #include <map> #include <set> #define inf (1<<30) #define N (500010) #define il inline #define RG register #define ll long long #define File(s) freopen(s".in","r",stdin),freopen(s".out","w",stdout) using namespace std; int ch [26],sum[20*N],ls[20*N],rs[20*N],rt ,len ,n,sz,cnt; string s ; il int gi(){ RG int x=0,q=1; RG char ch=getchar(); while ((ch<'0' || ch>'9') && ch!='-') ch=getchar(); if (ch=='-') q=-1,ch=getchar(); while (ch>='0' && ch<='9') x=x*10+ch-48,ch=getchar(); return q*x; } il void update(RG int &x,RG int l,RG int r,RG int p){ if (!x) x=++cnt; ++sum[x]; if (l==r) return; RG int mid=(l+r)>>1; p<=mid?update(ls[x],l,mid,p):update(rs[x],mid+1,r,p); return; } il int query(RG int x,RG int l,RG int r,RG int k){ if (l==r) return l; RG int mid=(l+r)>>1,tmp=sum[ls[x]]; return k<=tmp?query(ls[x],l,mid,k):query(rs[x],mid+1,r,k-tmp); } il void insert(string s,RG int len,RG int p){ RG int x=0,c; for (RG int i=len-1;i>=0;--i){ c=s[i]-97; if (!ch[x][c]) ch[x][c]=++sz; x=ch[x][c],update(rt[x],1,n,p); } return; } il int find(string s,RG int len,RG int k){ RG int x=0,c; for (RG int i=len-1;i>=0;--i) c=s[i]-97,x=ch[x][c]; return sum[rt[x]]>=k?query(rt[x],1,n,k):-1; } il void work(){ n=gi(); for (RG int i=1;i<=n;++i) cin>>s[i],len[i]=s[i].length(),insert(s[i],len[i],i); for (RG int i=1,k;i<=n;++i) k=gi(),printf("%d\n",find(s[i],len[i],k)); return; } int main(){ File("kpm"); work(); return 0; }
相关文章推荐
- BZOJ 3439 Kpm的MC密码 Trie树+可持久化线段树
- BZOJ-3439:Kpm的MC密码(Trie+DFS序+主席树)
- 【BZOJ3439】Kpm的MC密码 Trie树+可持久化线段树
- [BZOJ 3439]Kpm的MC密码
- 【BZOJ 3439】Kpm的MC密码 主席树+trie树
- 【BZOJ】【3439】Kpm的MC密码
- BZOJ 3439: Kpm的MC密码( trie + DFS序 + 主席树 )
- [BZOJ 3439]Kpm的MC密码
- [BZOJ]3439: Kpm的MC密码 trie树+主席树(线段树合并)
- 【bzoj3439】KPM的MC密码
- 【bzoj3439】Kpm的MC密码 可持久化Trie树
- BZOJ3439 Kpm的MC密码
- BZOJ3439 KPM的MC密码
- bzoj 3439: Kpm的MC密码
- BZOJ3439: Kpm的MC密码
- bzoj 3439 Kpm的MC密码(Trie+dfs序+主席树)
- 【BZOJ3439】 Kpm的MC密码 (TRIE+主席树)
- bzoj 3439: Kpm的MC密码
- 【bzoj3439】kpm的mc密码 题解
- BZOJ 3439 Kpm的MC密码