【BZOJ 3998】 3998: [TJOI2015]弦论 (SAM )
3998: [TJOI2015]弦论
Time Limit: 10 Sec Memory Limit: 256 MB
Submit: 2627 Solved: 881Description
对于一个给定长度为N的字符串,求它的第K小子串是什么。
Input
第一行是一个仅由小写英文字母构成的字符串S
第二行为两个整数T和K,T为0则表示不同位置的相同子串算作一个。T=1则表示不同位置的相同子串算作多个。K的意义如题所述。Output
输出仅一行,为一个数字串,为第K小的子串。如果子串数目不足K个,则输出-1
Sample Input
aabc
0 3Sample Output
aabHINT
N<=5*10^5
T<2K<=10^9Source
【分析】
建SAM,然后跑。
right数组要按照拓扑序来求啊!!!!
然后累计儿子的和的时候也要用拓扑序。
具体拓扑序:
for(int i=1;i<=tot;i++) v[t[i].step]++;
for(int i=1;i<=tot;i++) v[i]+=v[i-1];
for(int i=tot;i>=1;i--) q[v[t[i].step]--]=i;
类似后缀数组那里的了。
T=0,就right一开始都为1;T=1,就用right数组。
空串算一个串,一开始k++。
当然后缀数组也是可以的。
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
#define Maxn 500010 struct node
{
int pre,last,son[],step;
}t[Maxn*];
int rt[Maxn*],sm0[*Maxn],sm1[*Maxn];
int v[*Maxn],q[*Maxn]; struct sam
{
int last,tot;
void extend(int k)
{
int np=++tot,p=last;
t[np].step=t[last].step+;
rt[np]=;
while(p&&!t[p].son[k])
{
t[p].son[k]=np;
p=t[p].pre;
}
if(!p) t[np].pre=;
else
{
int q=t[p].son[k];
if(t[q].step==t[p].step+) t[np].pre=q;
else
{
int nq=++tot;
memcpy(t[nq].son,t[q].son,sizeof(t[nq].son));
t[nq].step=t[p].step+;
t[nq].pre=t[q].pre;
t[q].pre=t[np].pre=nq;
while(p&&t[p].son[k]==q)
{
t[p].son[k]=nq;
p=t[p].pre;
}
}
}
last=np;
}
void init()
{
for(int i=;i<=tot;i++) v[t[i].step]++;
for(int i=;i<=tot;i++) v[i]+=v[i-];
for(int i=tot;i>=;i--) q[v[t[i].step]--]=i; // for(int i=1;i<=tot;i++) rt[i]=1;
// for(int i=tot;i>=1;i--) rt[t[i].pre]+=rt[i];
// rt[1]=1;
for(int i=tot;i>=;i--)
{
int nw=q[i];
rt[t[nw].pre]+=rt[nw];
}rt[]=; for(int i=tot;i>=;i--)
{
int nw=q[i];
sm0[nw]=;sm1[nw]=rt[nw];
for(int j=;j<=;j++) if(t[nw].son[j])
{
sm0[nw]+=sm0[t[nw].son[j]];
sm1[nw]+=sm1[t[nw].son[j]];
}
}
}
void ffind(int opt,int k)
{
int sm,nw=;
k++;
while()
{
sm=opt?rt[nw]:;
for(int i=;i<=;i++) if(t[nw].son[i])
{
int ss=sm;
if(!opt) sm+=sm0[t[nw].son[i]];
else sm+=sm1[t[nw].son[i]];
if(sm>=k) {k-=ss;printf("%c",'a'+i-);nw=t[nw].son[i];break;}
}
if(!opt&&k==) break;
if(opt&&k<=rt[nw]) break;
}
printf("\n");
}
}sam; char s[Maxn]; int main()
{
scanf("%s",s);
int l=strlen(s);
sam.last=sam.tot=;
for(int i=;i<l;i++) sam.extend(s[i]-'a'+);
sam.init();
int opt,k;
scanf("%d%d",&opt,&k);
if(!opt&&k+>sm0[]) printf("-1\n");
else if(opt&&k+rt[]>sm1[]) printf("-1\n");
else sam.ffind(opt,k);
return ;
}
2017-04-17 13:59:36
【BZOJ 3998】 3998: [TJOI2015]弦论 (SAM )的更多相关文章
- bzoj3998: [TJOI2015]弦论(SAM+dfs)
3998: [TJOI2015]弦论 题目:传送门 题解: SAM的入门题目(很好的复习了SAM并加强Right集合的使用) 其实对于第K小的字符串直接从root开始一通DFS就好,因为son边是直接 ...
- luogu P3975 [TJOI2015]弦论 SAM
luogu P3975 [TJOI2015]弦论 链接 bzoj 思路 建出sam. 子串算多个的,统计preant tree的子树大小,否则就是大小为1 然后再统计sam的节点能走到多少串. 然后就 ...
- BZOJ3998:[TJOI2015]弦论(SAM)
Description 对于一个给定长度为N的字符串,求它的第K小子串是什么. Input 第一行是一个仅由小写英文字母构成的字符串S 第二行为两个整数T和K,T为0则表示不同位置的相同子串算作一个. ...
- BZOJ 3998: [TJOI2015]弦论 [后缀自动机 DP]
3998: [TJOI2015]弦论 Time Limit: 10 Sec Memory Limit: 256 MBSubmit: 2152 Solved: 716[Submit][Status] ...
- 【BZOJ3998】[TJOI2015]弦论 后缀自动机
[BZOJ3998][TJOI2015]弦论 Description 对于一个给定长度为N的字符串,求它的第K小子串是什么. Input 第一行是一个仅由小写英文字母构成的字符串S 第二行为两个整数T ...
- 题解-TJOI2015 弦论
TJOI2015 弦论 字符串 \(s\) 和 \(t\) 和 \(k\).如果 \(t=0\),不同位置的相同子串算 \(1\) 个:如果 \(t=1\),不同位置的相同子串算多个.求 \(k\) ...
- Luogu P3975 [TJOI2015]弦论
题目链接 \(Click\) \(Here\) 题目大意: 重复子串不算的第\(k\)大子串 重复子串计入的第\(k\)大子串 写法:后缀自动机. 和\(OI\) \(Wiki\)上介绍的写法不太一样 ...
- 洛谷 P3975 [TJOI2015]弦论 解题报告
P3975 [TJOI2015]弦论 题目描述 为了提高智商,ZJY开始学习弦论.这一天,她在<String theory>中看到了这样一道问题:对于一个给定的长度为\(n\)的字符串,求 ...
- BZOJ_3998_[TJOI2015]弦论_后缀自动机
BZOJ_3998_[TJOI2015]弦论_后缀自动机 Description 对于一个给定长度为N的字符串,求它的第K小子串是什么. Input 第一行是一个仅由小写英文字母构成的字符串S 第二行 ...
随机推荐
- Elasticsearch技术解析与实战(七)Elasticsearch批量操作
批量查询 1.如果查询的document是不同index下的不同type种的话 GET /_mget { "docs" : [ { "_index" : &qu ...
- 4163 hzwer与逆序对 (codevs + 权值线段树 + 求逆序对)
题目链接:http://codevs.cn/problem/4163/ 题目:
- bzoj 3123 可持久化线段树启发式合并
首先没有连边的操作的时候,我们可以用可持久化线段树来维护这棵树的信息,建立权值可持久化线段树,那么每个点继承父节点的线段树,当询问为x,y的时候我们可以询问rot[x]+rot[y]-rot[lca( ...
- 常见踩坑案例(一) subList引起FULLGC
计划真的赶不上变化,时间过得真快.废话不多说了,今天主要记录之前有同事遇到的一些坑分享出来. 一.封装类的应用会引起NPE异常 对于其他对象的应用,一般在使用之前会判断它是否为空,如果不为空才会使用它 ...
- JSON.stringify()——JS转JSON字符串
JSON.stringify() JSON 通常用于与服务端交换数据. 在向服务器发送数据时一般是字符串. 我们可以使用 JSON.stringify() 方法将 JavaScript 对象转换为字符 ...
- Java从零到企业级电商项目实战
欢迎关注我的微信公众号:"Java面试通关手册"(坚持原创,分享各种Java学习资源,面试题,优质文章,以及企业级Java实战项目回复关键字免费领取)回复关键字:"电商项 ...
- 看到了一篇博文,关于网卡的sniff模式,感觉相当好
@font-face { font-family: "Times New Roman"; }@font-face { font-family: "宋体"; }@ ...
- python使用unittest模块selenium访问斗鱼获取直播信息
import unittest from selenium import webdriver from bs4 import BeautifulSoup as bs class douyu(unitt ...
- Netty框架入门
一.概述 Netty是由JBOSS提供的一个java开源框架. Netty提供异步的.事件驱动的网络应用程序框架和工具,用以快速开发高性能.高可靠性的网络服务器和客户端程序. 二. ...
- effective c++读书笔记(一)
很早之前就听过这本书,找工作之前读一读.看了几页,个人感觉实在是生涩难懂,非常不符合中国人的思维方式.之前也有博主做过笔记,我来补充一些自己的理解. 我看有人记了笔记,还不错:http://www.3 ...