BZOJ3439: Kpm的MC密码
3439: Kpm的MC密码
Time Limit: 15 Sec Memory Limit: 256 MB
Submit: 166 Solved: 79
[Submit][Status]
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
cd
abcd
bcd
2
3
1
Sample Output
-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<len<=300000
HINT
Source
- #include<cstdio>
- #include<cstdlib>
- #include<iostream>
- #include<algorithm>
- #include<cstring>
- #include<queue>
- #include<vector>
- #include<map>
- #include<set>
- #include<stack>
- #include<string>
- #include<cmath>
- #include<cctype>
- using namespace std;
- const int maxlongint=;
- const int inf=;
- int trie[][],o=,fa[];
- vector<int> en[];
- int nx[];
- char a[];
- int root[];
- int lch[],rch[],num[],x=;
- int dfn[][],now=,n;
- int insert(int i,int l,int r,int j)
- {
- x++;
- int t=x;
- lch[t]=lch[i];
- rch[t]=rch[i];
- num[t]=num[i]+;
- if(l!=r)
- {
- int mid=(l+r)>>;
- if(j>mid)
- rch[t]=insert(rch[i],mid+,r,j);
- else
- lch[t]=insert(lch[i],l,mid,j);
- }
- return t;
- }
- int dfs(int i)
- {
- int n1;
- now++;
- int sz=en[i].size(),rt=root[now-];
- for(n1=;n1<sz;n1++)
- rt=insert(rt,,n,en[i][n1]);
- root[now]=rt;
- dfn[i][]=now;
- for(n1=;n1<;n1++)
- if(trie[i][n1])
- dfs(trie[i][n1]);
- now++;
- dfn[i][]=now;
- root[now]=root[now-];
- }
- int get(int i,int j,int k)
- {
- i=root[i-],j=root[j];
- if(num[j]-num[i]<k)
- return -;
- int l=,r=n;
- while(l!=r)
- {
- int mid=(l+r)>>;
- if(num[lch[j]]-num[lch[i]]>=k)
- {
- r=mid;
- i=lch[i];
- j=lch[j];
- }
- else
- {
- k-=num[lch[j]]-num[lch[i]];
- l=mid+;
- i=rch[i];
- j=rch[j];
- }
- }
- return l;
- }
- int main()
- {
- int n1,n2;
- cin>>n;
- for(n1=;n1<=n;n1++)
- {
- scanf("%s",a);
- int len=strlen(a);
- for(n2=;n2<=(len-)/;n2++)
- swap(a[n2],a[len-n2-]);
- int p=;
- for(n2=;n2<len;n2++)
- {
- if(trie[p][a[n2]-]==)
- {
- o++;
- trie[p][a[n2]-]=o;
- fa[o]=p;
- }
- p=trie[p][a[n2]-];
- if(n2==len-)
- {
- nx[n1]=p;
- en[p].push_back(n1);
- }
- }
- }
- dfs();
- int t1;
- for(n1=;n1<=n;n1++)
- {
- scanf("%d",&t1);
- printf("%d\n",get(dfn[nx[n1]][],dfn[nx[n1]][],t1));
- }
- }
我的:TLE
- #include<cstdio>
- #include<cstdlib>
- #include<cmath>
- #include<cstring>
- #include<algorithm>
- #include<iostream>
- #include<vector>
- #include<map>
- #include<set>
- #include<queue>
- #include<string>
- #define inf 1000000000
- #define maxn 1000000+5
- #define maxm 5000000
- #define eps 1e-10
- #define ll long long
- #define pa pair<int,int>
- #define for0(i,n) for(int i=0;i<=(n);i++)
- #define for1(i,n) for(int i=1;i<=(n);i++)
- #define for2(i,x,y) for(int i=(x);i<=(y);i++)
- #define for3(i,x,y) for(int i=(x);i>=(y);i--)
- #define mod 1000000007
- using namespace std;
- inline int read()
- {
- int x=,f=;char ch=getchar();
- while(ch<''||ch>''){if(ch=='-')f=-;ch=getchar();}
- while(ch>=''&&ch<=''){x=*x+ch-'';ch=getchar();}
- return x*f;
- }
- int n,m,cnt=,tot,now,s[maxm],ls[maxm],rs[maxm],t[maxn][],rt[maxn],dfn[maxn][],p[maxn];
- vector<int>G[maxn];
- char st[maxn];
- void update(int l,int r,int x,int &y,int z)
- {
- y=++tot;
- s[y]=s[x]+;
- if(l==r)return;
- ls[y]=ls[x];rs[y]=rs[x];
- int mid=(l+r)>>;
- if(z<=mid)update(l,mid,ls[x],ls[y],z);else update(mid+,r,rs[x],rs[y],z);
- }
- void dfs(int x)
- {
- dfn[x][]=++now;
- int sz=G[x].size(),y=rt[now-],yy=y;
- for0(i,sz-)update(,n,y,yy,G[x][i]),y=yy;
- rt[now]=yy;
- for0(i,)if(t[x][i])dfs(t[x][i]);
- dfn[x][]=++now;
- rt[now]=rt[now-];
- }
- int query(int x,int y,int k)
- {
- int l=,r=n,xx=rt[x-],yy=rt[y];
- if(s[yy]-s[xx]<k)return -;
- while(l!=r)
- {
- int mid=(l+r)>>;
- if(s[ls[yy]]-s[ls[xx]]>=k){xx=ls[xx];yy=ls[yy];r=mid;}
- else {k-=s[ls[yy]]-s[ls[xx]];xx=rs[xx];yy=rs[yy];l=mid+;}
- }
- return l;
- }
- int main()
- {
- freopen("input.txt","r",stdin);
- freopen("output.txt","w",stdout);
- n=read();
- for1(i,n)
- {
- memset(st,,sizeof(st));
- scanf("%s",st+);m=strlen(st+);
- now=;
- for3(j,m,)
- {
- int x=st[j]-'a';
- if(!t[now][x])t[now][x]=++cnt;
- now=t[now][x];
- }
- p[i]=now;G[now].push_back(i);
- }
- now=;
- dfs();
- for1(i,n)
- {
- int k=read();
- printf("%d\n",query(dfn[p[i]][],dfn[p[i]][],k));
- }
- return ;
- }
BZOJ3439: Kpm的MC密码的更多相关文章
- BZOJ3439 Kpm的MC密码(可持久化trie)
将串反过来就变成查询前缀了.考虑建一棵可持久化trie,查询时二分答案,均摊一下复杂度即为O(mlogn). #include<iostream> #include<cstdio&g ...
- 【BZOJ3439】 Kpm的MC密码 (TRIE+主席树)
3439: Kpm的MC密码 Description 背景 想Kpm当年为了防止别人随便进入他的MC,给他的PC设了各种奇怪的密码和验证问题(不要问我他是怎么设的...),于是乎,他现在理所当然地忘记 ...
- 【BZOJ3439】Kpm的MC密码 Trie树+可持久化线段树
[BZOJ3439]Kpm的MC密码 Description 背景 想Kpm当年为了防止别人随便进入他的MC,给他的PC设了各种奇怪的密码和验证问题(不要问我他是怎么设的...),于是乎,他现在理所当 ...
- 【BZOJ】【3439】Kpm的MC密码
Trie树/可持久化线段树 神题啊……搞了我一下午= =(其实第233个提交也是我的) 我一开始的思路:这个找kpm串的过程,其实就跟在AC自动机上沿fail倒着往下走是差不多的(看当前是哪些点的后缀 ...
- BZOJ 3439: Kpm的MC密码( trie + DFS序 + 主席树 )
把串倒过来插进trie上, 那么一个串的kpm串就是在以这个串最后一个为根的子树, 子树k大值的经典问题用dfs序+可持久化线段树就可以O(NlogN)解决 --------------------- ...
- 【BZOJ3439】Kpm的MC密码 trie树+主席树
Description 背景 想Kpm当年为了防止别人随便进入他的MC,给他的PC设了各种奇怪的密码和验证问题(不要问我他是怎么设的...),于是乎,他现在理所当然地忘记了密码,只能来解答那些神奇的身 ...
- 【bzoj3439】Kpm的MC密码 可持久化Trie树
题目描述 背景 想Kpm当年为了防止别人随便进入他的MC,给他的PC设了各种奇怪的密码和验证问题(不要问我他是怎么设的...),于是乎,他现在理所当然地忘记了密码,只能来解答那些神奇的身份验证问题了. ...
- BZOJ-3439:Kpm的MC密码(Trie+DFS序+主席树)
背景 想Kpm当年为了防止别人随便进入他的MC,给他的PC设了各种奇怪的密码和验证问题(不要问我他是怎么设的...),于是乎,他现在理所当然地忘记了密码,只能来解答那些神奇的身份验证问题了... 描述 ...
- 【bzoj3439】kpm的mc密码 题解
题目大意: 有n个字符串,编号为1~n,求每一个字符串在其他字符串中以它为后缀的字符串中编号第k小的字符串的编号. 思路: 将字符串倒过来建Trie,记录每个结尾节点的编号(可能会有重复,所以开一个v ...
随机推荐
- 路E施工管理ERP系统
前 景 目前公路工程由于点多.线长.面广.周期久.投资大等原因,管理很难到位,施工过程中存在着大量问题: 规章制度欠缺或不健全,即便是有好的规章制度,在施工过程中也往往形同虚设,不能与现场施 ...
- CSS伪类选择器和伪元素选择器
CSS的伪类选择器常用的是link/visited/hover/active,分别对应未访问.已访问过.鼠标悬停.鼠标按下时的样式,常用于链接,使用时要按此顺序依次写CSS,不能乱 a:link{ba ...
- web前端:html
一.理解表单的作用 1.web 应用程序不仅仅是给用户显示数据,还应该给用户提供一个可以输入数据的图形用户界面.表单的主要作用在于在网页上提供一个图形用户界面,已采集和提交用户输入的数据. 2.htm ...
- Handler 原理分析和使用之HandlerThread
前面已经提到过Handler的原理以及Handler的三种用法.这里做一个非常简单的一个总结: Handler 是跨线程的Message处理.负责把Message推送到MessageQueue和处理. ...
- LIB库加载方法-引用百度百科
LIB库加载方法,有三种,如下: 1.LIB文件直接加入到工程文件列表中 在VC中打开File View一页,选中工程名,单击鼠标右键,然后选中\"Add Files to Project\ ...
- fmt:formatDate标签的输出格式
http://blog.csdn.net/lidawei201/article/details/7197834
- CSS 分组 和 嵌套 选择器
Grouping Selectors 在样式表中有很多具有相同样式的元素. h1{color:green;}h2{color:green;}p{color:green;} 为了尽量减少代码,你可以使用 ...
- CentOS 6.4 64位 安装 apache-tomcat-6.0.43
下载 tomcat: 地址:http://mirrors.hust.edu.cn/apache/tomcat/tomcat-6/v6.0.43/bin/apache-tomcat-6.0.43.tar ...
- php和js根据子网掩码和ip计算子网
php $ip = '192.168.6.1'; $mask = '255.255.2.0'; $sub_net = array();//子网 $ip_explode = explode('.', $ ...
- jquery技巧(持续更新。。)
(1)集合处理功能 //为索引为0,1,2的元素分别设置不同的字体颜色 $('p').each(function(i){ this.styl ...