【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 第二行 ...
随机推荐
- vue.js devtools-------调试vue.js的开发者插件
vue.js devtools插件: 作用: 以往我们在进行测试代码的时候,直接在console进行查看,其实这个插件雷同于控制台,只不过在vue里面,将需要查看的数据存放在一个变量里面了~ 效果图: ...
- JavaScript三种绑定事件的方式
JavaScript三种绑定事件的方式: 1. <div id="btn" onclick="clickone()"></div> // ...
- java使用simpleDateFormat格式化日期 时间
时间日期标识符: yyyy:年 MM:月 dd:日 hh:1~12小时制(1-12) HH:24小时制(0-23) mm:分 ss:秒 S:毫秒 E:星期几 D:一年中的第几天 F:一月中的第几个星期 ...
- 图片轮播器——jquery插件
下载:http://files.cnblogs.com/files/wordblog/jiaoben828.rar
- Codeforces Round #466
A. Points on the line 题意 给定一条直线上\(n\)个点,要求去掉最少的点,使得直线上相距最远的两个点的距离\(\leq d\). 思路 枚举长度为\(d\)的区间. Code ...
- 我的Apache又挂了之apache错误:server's fully qualified domain name, using 127.0.0.1. Set the 'ServerName'
表示物理机装Apache然后有时候关机会忘了关闭Apache然后长此以往会导致各种Apache起不来的缘故,上一次已经出现过一次.今天又出现了 再次记录一下解决的方法. 1.查看错误日志 /var/l ...
- python基础之常用的高阶函数
前言 高阶函数指的是能接收函数作为参数的函数或类:python中有一些内置的高阶函数,在某些场合使用可以提高代码的效率. map() map函数可以把一个迭代对象转换成另一个可迭代对象,不过在pyth ...
- 浅谈iOS多线程
浅谈iOS多线程 首先,先看看进程和线程的概念. 图1.1 这一块不难理解,重点点下他们的几个重要区别: 1,地址空间和资源:进程可以申请和拥有系统资源,线程不行.资源进程间相互独立,同一进程的各线程 ...
- SSL handshake failed: SSL error: Key usage violation in certificate has been detected.
sudo apt-get install libneon27-dev cd /usr/libsudo mv libneon-gnutls.so.27 libneon-gnutls.so.27.olds ...
- python近期遇到的一些面试问题(三)
python近期遇到的一些面试问题(三) 整理一下最近被问到的一些高频率的面试问题.总结一下方便日后复习巩固用,同时希望可以帮助一些朋友们. 前两期点这↓ python近期遇到的一些面试问题(一) p ...