3998: [TJOI2015]弦论

Time Limit: 10 Sec  Memory Limit: 256 MB
Submit: 2627  Solved: 881

Description

对于一个给定长度为N的字符串,求它的第K小子串是什么。

Input

第一行是一个仅由小写英文字母构成的字符串S

第二行为两个整数T和K,T为0则表示不同位置的相同子串算作一个。T=1则表示不同位置的相同子串算作多个。K的意义如题所述。

Output

输出仅一行,为一个数字串,为第K小的子串。如果子串数目不足K个,则输出-1

Sample Input

aabc
0 3

Sample Output

aab

HINT

N<=5*10^5

T<2
K<=10^9

Source

【分析】

  建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 )的更多相关文章

  1. bzoj3998: [TJOI2015]弦论(SAM+dfs)

    3998: [TJOI2015]弦论 题目:传送门 题解: SAM的入门题目(很好的复习了SAM并加强Right集合的使用) 其实对于第K小的字符串直接从root开始一通DFS就好,因为son边是直接 ...

  2. luogu P3975 [TJOI2015]弦论 SAM

    luogu P3975 [TJOI2015]弦论 链接 bzoj 思路 建出sam. 子串算多个的,统计preant tree的子树大小,否则就是大小为1 然后再统计sam的节点能走到多少串. 然后就 ...

  3. BZOJ3998:[TJOI2015]弦论(SAM)

    Description 对于一个给定长度为N的字符串,求它的第K小子串是什么. Input 第一行是一个仅由小写英文字母构成的字符串S 第二行为两个整数T和K,T为0则表示不同位置的相同子串算作一个. ...

  4. BZOJ 3998: [TJOI2015]弦论 [后缀自动机 DP]

    3998: [TJOI2015]弦论 Time Limit: 10 Sec  Memory Limit: 256 MBSubmit: 2152  Solved: 716[Submit][Status] ...

  5. 【BZOJ3998】[TJOI2015]弦论 后缀自动机

    [BZOJ3998][TJOI2015]弦论 Description 对于一个给定长度为N的字符串,求它的第K小子串是什么. Input 第一行是一个仅由小写英文字母构成的字符串S 第二行为两个整数T ...

  6. 题解-TJOI2015 弦论

    TJOI2015 弦论 字符串 \(s\) 和 \(t\) 和 \(k\).如果 \(t=0\),不同位置的相同子串算 \(1\) 个:如果 \(t=1\),不同位置的相同子串算多个.求 \(k\) ...

  7. Luogu P3975 [TJOI2015]弦论

    题目链接 \(Click\) \(Here\) 题目大意: 重复子串不算的第\(k\)大子串 重复子串计入的第\(k\)大子串 写法:后缀自动机. 和\(OI\) \(Wiki\)上介绍的写法不太一样 ...

  8. 洛谷 P3975 [TJOI2015]弦论 解题报告

    P3975 [TJOI2015]弦论 题目描述 为了提高智商,ZJY开始学习弦论.这一天,她在<String theory>中看到了这样一道问题:对于一个给定的长度为\(n\)的字符串,求 ...

  9. BZOJ_3998_[TJOI2015]弦论_后缀自动机

    BZOJ_3998_[TJOI2015]弦论_后缀自动机 Description 对于一个给定长度为N的字符串,求它的第K小子串是什么. Input 第一行是一个仅由小写英文字母构成的字符串S 第二行 ...

随机推荐

  1. Elasticsearch技术解析与实战(七)Elasticsearch批量操作

    批量查询 1.如果查询的document是不同index下的不同type种的话 GET /_mget { "docs" : [ { "_index" : &qu ...

  2. 4163 hzwer与逆序对 (codevs + 权值线段树 + 求逆序对)

    题目链接:http://codevs.cn/problem/4163/ 题目:

  3. bzoj 3123 可持久化线段树启发式合并

    首先没有连边的操作的时候,我们可以用可持久化线段树来维护这棵树的信息,建立权值可持久化线段树,那么每个点继承父节点的线段树,当询问为x,y的时候我们可以询问rot[x]+rot[y]-rot[lca( ...

  4. 常见踩坑案例(一) subList引起FULLGC

    计划真的赶不上变化,时间过得真快.废话不多说了,今天主要记录之前有同事遇到的一些坑分享出来. 一.封装类的应用会引起NPE异常 对于其他对象的应用,一般在使用之前会判断它是否为空,如果不为空才会使用它 ...

  5. JSON.stringify()——JS转JSON字符串

    JSON.stringify() JSON 通常用于与服务端交换数据. 在向服务器发送数据时一般是字符串. 我们可以使用 JSON.stringify() 方法将 JavaScript 对象转换为字符 ...

  6. Java从零到企业级电商项目实战

    欢迎关注我的微信公众号:"Java面试通关手册"(坚持原创,分享各种Java学习资源,面试题,优质文章,以及企业级Java实战项目回复关键字免费领取)回复关键字:"电商项 ...

  7. 看到了一篇博文,关于网卡的sniff模式,感觉相当好

    @font-face { font-family: "Times New Roman"; }@font-face { font-family: "宋体"; }@ ...

  8. python使用unittest模块selenium访问斗鱼获取直播信息

    import unittest from selenium import webdriver from bs4 import BeautifulSoup as bs class douyu(unitt ...

  9. Netty框架入门

    一.概述     Netty是由JBOSS提供的一个java开源框架.     Netty提供异步的.事件驱动的网络应用程序框架和工具,用以快速开发高性能.高可靠性的网络服务器和客户端程序.   二. ...

  10. effective c++读书笔记(一)

    很早之前就听过这本书,找工作之前读一读.看了几页,个人感觉实在是生涩难懂,非常不符合中国人的思维方式.之前也有博主做过笔记,我来补充一些自己的理解. 我看有人记了笔记,还不错:http://www.3 ...