【BZOJ3439】Kpm的MC密码 Trie树+可持久化线段树
【BZOJ3439】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
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
题解:写完可持久化Trie树和各种主席树这道题就显得很水了~
将单词倒序扔到Trie树中,然后根据Trie树中的父子关系在重新构建一棵树。这样就满足新树中一个节点的子树中的所有节点都是该节点的kpm串,于是直接用主席树维护DFS序即可。
结果交上去秒WA,原因是可能有重复的字符串!!所以要把它们合成一个串考虑,用vector存一下就好了(当然,我依然是用的链表来存)
- #include <cstdio>
- #include <cstring>
- #include <iostream>
- using namespace std;
- struct node
- {
- int ch[26],from,org;
- }p[300010];
- struct sag
- {
- int ls,rs,siz;
- }s[2000010];
- int n,m,cnt,sum,tot;
- int pos[100010],to[100010],next[100010],head[100010],q1[100010],q2[100010],rt[100010],fa[100010];
- int pre[100010];
- char str[3000010];
- void add(int a,int b)
- {
- to[cnt]=b,next[cnt]=head[a],head[a]=cnt++;
- }
- void insert(int x,int &y,int l,int r,int pos)
- {
- if(pos>r) return ;
- y=++tot;
- if(l==r)
- {
- s[y].siz=1;
- return ;
- }
- int mid=l+r>>1;
- if(pos<=mid) s[y].rs=s[x].rs,insert(s[x].ls,s[y].ls,l,mid,pos);
- else s[y].ls=s[x].ls,insert(s[x].rs,s[y].rs,mid+1,r,pos);
- s[y].siz=s[s[y].ls].siz+s[s[y].rs].siz;
- }
- int query(int x,int y,int l,int r,int k)
- {
- if(l==r) return l;
- int mid=l+r>>1,sm=s[s[y].ls].siz-s[s[x].ls].siz;
- if(sm>=k) return query(s[x].ls,s[y].ls,l,mid,k);
- return query(s[x].rs,s[y].rs,mid+1,r,k-sm);
- }
- void dfs(int x)
- {
- q1[x]=q1[0];
- int i;
- for(i=x;i;i=pre[i]) insert(rt[q1[0]],rt[q1[0]+1],1,n,i),q1[0]++;
- for(i=head[x];i!=-1;i=next[i]) dfs(to[i]);
- q2[x]=q1[0];
- for(i=pre[x];i;i=pre[i]) q1[i]=q1[x],q2[i]=q2[x];
- }
- int main()
- {
- scanf("%d",&n);
- int i,j,a,b,u;
- sum=1;
- memset(head,-1,sizeof(head));
- for(i=1;i<=n;i++)
- {
- scanf("%s",str),a=strlen(str);
- u=1;
- for(j=a-1;j>=0;j--)
- {
- b=str[j]-'a';
- if(!p[u].ch[b]) p[u].ch[b]=++sum,p[p[u].ch[b]].from=u;
- u=p[u].ch[b];
- }
- pre[i]=p[u].org,p[u].org=i,pos[i]=u;
- }
- for(i=1;i<=n;i++)
- {
- if(p[pos[i]].org!=i) continue;
- for(j=p[pos[i]].from;j!=1&&!p[j].org;j=p[j].from);
- fa[i]=p[j].org,add(fa[i],i);
- }
- dfs(0);
- for(i=1;i<=n;i++)
- {
- scanf("%d",&a);
- if(q2[i]-q1[i]<a) printf("-1\n");
- else printf("%d\n",query(rt[q1[i]],rt[q2[i]],1,n,a));
- }
- return 0;
- }
【BZOJ3439】Kpm的MC密码 Trie树+可持久化线段树的更多相关文章
- bzoj 3439: Kpm的MC密码 Trie+动态开点线段树
题目大意: http://www.lydsy.com/JudgeOnline/problem.php?id=3439 题解: 首先我们发现这道题要查的是后缀不是前缀. 如果查前缀就可以迅速查找到字符串 ...
- 主席树||可持久化线段树+离散化 || 莫队+分块 ||BZOJ 3585: mex || Luogu P4137 Rmq Problem / mex
题面:Rmq Problem / mex 题解: 先离散化,然后插一堆空白,大体就是如果(对于以a.data<b.data排序后的A)A[i-1].data+1!=A[i].data,则插一个空 ...
- [BZOJ 4771]七彩树(可持久化线段树+树上差分)
[BZOJ 4771]七彩树(可持久化线段树+树上差分) 题面 给定一棵n个点的有根树,编号依次为1到n,其中1号点是根节点.每个节点都被染上了某一种颜色,其中第i个节点的颜色为c[i].如果c[i] ...
- BZOJ 3439: Kpm的MC密码( trie + DFS序 + 主席树 )
把串倒过来插进trie上, 那么一个串的kpm串就是在以这个串最后一个为根的子树, 子树k大值的经典问题用dfs序+可持久化线段树就可以O(NlogN)解决 --------------------- ...
- BZOJ3439: Kpm的MC密码
3439: Kpm的MC密码 Time Limit: 15 Sec Memory Limit: 256 MBSubmit: 166 Solved: 79[Submit][Status] Descr ...
- BZOJ 3439 Kpm的MCpassword Trie树+可持久化线段树
题目大意:给定n个字符串,对于每一个字符串求以这个字符串为后缀的字符串中第k小的编号 首先将字符串反转 那么就变成了对于每一个字符串求以这个字符串为前缀的字符串中第k小的编号 然后考虑对字符串排序 那 ...
- BZOJ 3483 SGU505 Prefixes and suffixes(字典树+可持久化线段树)
[题目链接] http://www.lydsy.com/JudgeOnline/problem.php?id=3483 [题目大意] 给出一些串,同时给出m对前缀后缀,询问有多少串满足给出的前缀后缀模 ...
- 归并树 划分树 可持久化线段树(主席树) 入门题 hdu 2665
如果题目给出1e5的数据范围,,以前只会用n*log(n)的方法去想 今天学了一下两三种n*n*log(n)的数据结构 他们就是大名鼎鼎的 归并树 划分树 主席树,,,, 首先来说两个问题,,区间第k ...
- 主席树[可持久化线段树](hdu 2665 Kth number、SP 10628 Count on a tree、ZOJ 2112 Dynamic Rankings、codeforces 813E Army Creation、codeforces960F:Pathwalks )
在今天三黑(恶意评分刷上去的那种)两紫的智推中,突然出现了P3834 [模板]可持久化线段树 1(主席树)就突然有了不详的预感2333 果然...然后我gg了!被大佬虐了! hdu 2665 Kth ...
随机推荐
- MVC中Area的另一种用法
[摘要]本文只是为一行代码而分享 context.MapRoute("API", "api/{controller}/{action}", new { }, n ...
- @@identity、scope_identity()、IDENT_CURRENT('tablename')函数的区别
@@IDENTITY 和SCOPE_IDENTITY 返回在当前会话中的任何表内所生成的最后一个标识值.但是,SCOPE_IDENTITY 只返回插入到当前作用域中的值:@@IDENTITY 不受限于 ...
- jQuery中的text(),html(),val()有什么区别
text():获取或者改变指定元素的文本html():获取或改变指定元素的html元素以及文本val():获取或者改变指定元素的value值(一般是表单元素) 以上3个都是jquery类库中的语法 第 ...
- 140726暑期培训.txt
1. 输入多组数据的时候 while(scanf("%s",s)!=EOF) while(gets(s)!=NULL) 用gets和scanf不 ...
- 动态添加定时任务-quartz定时器
Quartz动态添加.修改和删除定时任务 在项目中有一个需求,需要灵活配置调度任务时间,刚开始用的Java自带的java.util.Timer类,通过调度一个java.util.TimerTask任务 ...
- zookeeper伪分布式安装
本文介绍zookeeper伪分布式安装. 所谓 “伪分布式集群” 就是在1台PC中启动多个zookeeper的实例.“完全分布式集群” 是每1台PC启动1个ZooKeeper实例. 由于我的测试环境P ...
- PyCharm Python迁移项目
把整个项目文件迁移过去后,执行文件会报不能执行XX,系统找不到指定的文件. 此时把当前的这个文件名字改一下,再运行,修改提示的错误.等错误全部修改,可以正常运行后,再把文件名改回去
- vi全文替换命令
1,$s/str1/str2/g:从第一行到最后一行把str1替换成str2
- linux--jdk安装与配置
此处以centos下jdkjdk1.8.0_161安装(此处为rpm安装事例)为例 1.java官网下载页找到对应版本的jdk下载链接地址 2.下载对应版本的rmp包到服务器,执行如下指令: wget ...
- cocos2dx 富文本框,支持换行,支持神情(支持汉字截断无乱码)
cocos2dx 富文本框,支持换行,支持表情(支持汉字截断无乱码) 小工在做了一个游戏聊天功能,里面用到插入表情的富文本和换行的问题: 先看效果,不是你要的效果,可return:(截图由于:输入的问 ...