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

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<len<=300000

HINT

 

Source

题解:
真是一道好题!
很容易想到把字符串反转之后插入一棵trie树,然后s的kpm串就是它的子树,然后dfs序处理一下把子树内的信息变成连续的就可以用主席树求第k小了。
刚开始把kpm串的定义看反了,然后就把每个点到根节点的主席树建了出来。。。
实现的时候有很多细节,我参考了某大牛的代码
代码:
  1. #include<cstdio>
  2. #include<cstdlib>
  3. #include<iostream>
  4. #include<algorithm>
  5. #include<cstring>
  6. #include<queue>
  7. #include<vector>
  8. #include<map>
  9. #include<set>
  10. #include<stack>
  11. #include<string>
  12. #include<cmath>
  13. #include<cctype>
  14. using namespace std;
  15. const int maxlongint=;
  16. const int inf=;
  17. int trie[][],o=,fa[];
  18. vector<int> en[];
  19. int nx[];
  20. char a[];
  21. int root[];
  22. int lch[],rch[],num[],x=;
  23. int dfn[][],now=,n;
  24. int insert(int i,int l,int r,int j)
  25. {
  26. x++;
  27. int t=x;
  28. lch[t]=lch[i];
  29. rch[t]=rch[i];
  30. num[t]=num[i]+;
  31. if(l!=r)
  32. {
  33. int mid=(l+r)>>;
  34. if(j>mid)
  35. rch[t]=insert(rch[i],mid+,r,j);
  36. else
  37. lch[t]=insert(lch[i],l,mid,j);
  38. }
  39. return t;
  40. }
  41. int dfs(int i)
  42. {
  43. int n1;
  44. now++;
  45. int sz=en[i].size(),rt=root[now-];
  46. for(n1=;n1<sz;n1++)
  47. rt=insert(rt,,n,en[i][n1]);
  48. root[now]=rt;
  49. dfn[i][]=now;
  50. for(n1=;n1<;n1++)
  51. if(trie[i][n1])
  52. dfs(trie[i][n1]);
  53. now++;
  54. dfn[i][]=now;
  55. root[now]=root[now-];
  56. }
  57. int get(int i,int j,int k)
  58. {
  59. i=root[i-],j=root[j];
  60. if(num[j]-num[i]<k)
  61. return -;
  62. int l=,r=n;
  63. while(l!=r)
  64. {
  65. int mid=(l+r)>>;
  66. if(num[lch[j]]-num[lch[i]]>=k)
  67. {
  68. r=mid;
  69. i=lch[i];
  70. j=lch[j];
  71. }
  72. else
  73. {
  74. k-=num[lch[j]]-num[lch[i]];
  75. l=mid+;
  76. i=rch[i];
  77. j=rch[j];
  78. }
  79. }
  80. return l;
  81. }
  82. int main()
  83. {
  84. int n1,n2;
  85. cin>>n;
  86. for(n1=;n1<=n;n1++)
  87. {
  88. scanf("%s",a);
  89. int len=strlen(a);
  90. for(n2=;n2<=(len-)/;n2++)
  91. swap(a[n2],a[len-n2-]);
  92. int p=;
  93. for(n2=;n2<len;n2++)
  94. {
  95. if(trie[p][a[n2]-]==)
  96. {
  97. o++;
  98. trie[p][a[n2]-]=o;
  99. fa[o]=p;
  100. }
  101. p=trie[p][a[n2]-];
  102. if(n2==len-)
  103. {
  104. nx[n1]=p;
  105. en[p].push_back(n1);
  106. }
  107. }
  108. }
  109. dfs();
  110. int t1;
  111. for(n1=;n1<=n;n1++)
  112. {
  113. scanf("%d",&t1);
  114. printf("%d\n",get(dfn[nx[n1]][],dfn[nx[n1]][],t1));
  115. }
  116. }

我的:TLE

  1. #include<cstdio>
  2. #include<cstdlib>
  3. #include<cmath>
  4. #include<cstring>
  5. #include<algorithm>
  6. #include<iostream>
  7. #include<vector>
  8. #include<map>
  9. #include<set>
  10. #include<queue>
  11. #include<string>
  12. #define inf 1000000000
  13. #define maxn 1000000+5
  14. #define maxm 5000000
  15. #define eps 1e-10
  16. #define ll long long
  17. #define pa pair<int,int>
  18. #define for0(i,n) for(int i=0;i<=(n);i++)
  19. #define for1(i,n) for(int i=1;i<=(n);i++)
  20. #define for2(i,x,y) for(int i=(x);i<=(y);i++)
  21. #define for3(i,x,y) for(int i=(x);i>=(y);i--)
  22. #define mod 1000000007
  23. using namespace std;
  24. inline int read()
  25. {
  26. int x=,f=;char ch=getchar();
  27. while(ch<''||ch>''){if(ch=='-')f=-;ch=getchar();}
  28. while(ch>=''&&ch<=''){x=*x+ch-'';ch=getchar();}
  29. return x*f;
  30. }
  31. int n,m,cnt=,tot,now,s[maxm],ls[maxm],rs[maxm],t[maxn][],rt[maxn],dfn[maxn][],p[maxn];
  32. vector<int>G[maxn];
  33. char st[maxn];
  34. void update(int l,int r,int x,int &y,int z)
  35. {
  36. y=++tot;
  37. s[y]=s[x]+;
  38. if(l==r)return;
  39. ls[y]=ls[x];rs[y]=rs[x];
  40. int mid=(l+r)>>;
  41. if(z<=mid)update(l,mid,ls[x],ls[y],z);else update(mid+,r,rs[x],rs[y],z);
  42. }
  43. void dfs(int x)
  44. {
  45. dfn[x][]=++now;
  46. int sz=G[x].size(),y=rt[now-],yy=y;
  47. for0(i,sz-)update(,n,y,yy,G[x][i]),y=yy;
  48. rt[now]=yy;
  49. for0(i,)if(t[x][i])dfs(t[x][i]);
  50. dfn[x][]=++now;
  51. rt[now]=rt[now-];
  52. }
  53. int query(int x,int y,int k)
  54. {
  55. int l=,r=n,xx=rt[x-],yy=rt[y];
  56. if(s[yy]-s[xx]<k)return -;
  57. while(l!=r)
  58. {
  59. int mid=(l+r)>>;
  60. if(s[ls[yy]]-s[ls[xx]]>=k){xx=ls[xx];yy=ls[yy];r=mid;}
  61. else {k-=s[ls[yy]]-s[ls[xx]];xx=rs[xx];yy=rs[yy];l=mid+;}
  62. }
  63. return l;
  64. }
  65. int main()
  66. {
  67. freopen("input.txt","r",stdin);
  68. freopen("output.txt","w",stdout);
  69. n=read();
  70. for1(i,n)
  71. {
  72. memset(st,,sizeof(st));
  73. scanf("%s",st+);m=strlen(st+);
  74. now=;
  75. for3(j,m,)
  76. {
  77. int x=st[j]-'a';
  78. if(!t[now][x])t[now][x]=++cnt;
  79. now=t[now][x];
  80. }
  81. p[i]=now;G[now].push_back(i);
  82. }
  83. now=;
  84. dfs();
  85. for1(i,n)
  86. {
  87. int k=read();
  88. printf("%d\n",query(dfn[p[i]][],dfn[p[i]][],k));
  89. }
  90. return ;
  91. }

BZOJ3439: Kpm的MC密码的更多相关文章

  1. BZOJ3439 Kpm的MC密码(可持久化trie)

    将串反过来就变成查询前缀了.考虑建一棵可持久化trie,查询时二分答案,均摊一下复杂度即为O(mlogn). #include<iostream> #include<cstdio&g ...

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

    3439: Kpm的MC密码 Description 背景 想Kpm当年为了防止别人随便进入他的MC,给他的PC设了各种奇怪的密码和验证问题(不要问我他是怎么设的...),于是乎,他现在理所当然地忘记 ...

  3. 【BZOJ3439】Kpm的MC密码 Trie树+可持久化线段树

    [BZOJ3439]Kpm的MC密码 Description 背景 想Kpm当年为了防止别人随便进入他的MC,给他的PC设了各种奇怪的密码和验证问题(不要问我他是怎么设的...),于是乎,他现在理所当 ...

  4. 【BZOJ】【3439】Kpm的MC密码

    Trie树/可持久化线段树 神题啊……搞了我一下午= =(其实第233个提交也是我的) 我一开始的思路:这个找kpm串的过程,其实就跟在AC自动机上沿fail倒着往下走是差不多的(看当前是哪些点的后缀 ...

  5. BZOJ 3439: Kpm的MC密码( trie + DFS序 + 主席树 )

    把串倒过来插进trie上, 那么一个串的kpm串就是在以这个串最后一个为根的子树, 子树k大值的经典问题用dfs序+可持久化线段树就可以O(NlogN)解决 --------------------- ...

  6. 【BZOJ3439】Kpm的MC密码 trie树+主席树

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

  7. 【bzoj3439】Kpm的MC密码 可持久化Trie树

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

  8. BZOJ-3439:Kpm的MC密码(Trie+DFS序+主席树)

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

  9. 【bzoj3439】kpm的mc密码 题解

    题目大意: 有n个字符串,编号为1~n,求每一个字符串在其他字符串中以它为后缀的字符串中编号第k小的字符串的编号. 思路: 将字符串倒过来建Trie,记录每个结尾节点的编号(可能会有重复,所以开一个v ...

随机推荐

  1. 路E施工管理ERP系统

      前  景   目前公路工程由于点多.线长.面广.周期久.投资大等原因,管理很难到位,施工过程中存在着大量问题: 规章制度欠缺或不健全,即便是有好的规章制度,在施工过程中也往往形同虚设,不能与现场施 ...

  2. CSS伪类选择器和伪元素选择器

    CSS的伪类选择器常用的是link/visited/hover/active,分别对应未访问.已访问过.鼠标悬停.鼠标按下时的样式,常用于链接,使用时要按此顺序依次写CSS,不能乱 a:link{ba ...

  3. web前端:html

    一.理解表单的作用 1.web 应用程序不仅仅是给用户显示数据,还应该给用户提供一个可以输入数据的图形用户界面.表单的主要作用在于在网页上提供一个图形用户界面,已采集和提交用户输入的数据. 2.htm ...

  4. Handler 原理分析和使用之HandlerThread

    前面已经提到过Handler的原理以及Handler的三种用法.这里做一个非常简单的一个总结: Handler 是跨线程的Message处理.负责把Message推送到MessageQueue和处理. ...

  5. LIB库加载方法-引用百度百科

    LIB库加载方法,有三种,如下: 1.LIB文件直接加入到工程文件列表中 在VC中打开File View一页,选中工程名,单击鼠标右键,然后选中\"Add Files to Project\ ...

  6. fmt:formatDate标签的输出格式

    http://blog.csdn.net/lidawei201/article/details/7197834

  7. CSS 分组 和 嵌套 选择器

    Grouping Selectors 在样式表中有很多具有相同样式的元素. h1{color:green;}h2{color:green;}p{color:green;} 为了尽量减少代码,你可以使用 ...

  8. 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 ...

  9. php和js根据子网掩码和ip计算子网

    php $ip = '192.168.6.1'; $mask = '255.255.2.0'; $sub_net = array();//子网 $ip_explode = explode('.', $ ...

  10. jquery技巧(持续更新。。)

    (1)集合处理功能         //为索引为0,1,2的元素分别设置不同的字体颜色         $('p').each(function(i){               this.styl ...