题目描述

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

输入

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

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

输出

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

样例输入

aabc
0 3

样例输出

aab


题解

后缀自动机+dp

先对原串建立后缀自动机,然后在其上面跑dp统计每个节点开始的串的个数。

设f[i]表示与位置i有相同前缀的串的个数。

那么当T=0时,显然f[i]=∑f[son[i]]+1。

当T=1时,f[i]=∑f[son[i]]+|right[i]|,需要统计right集合的大小,也即统计parent树中子树内有多少个叶子结点,这个递推一下即可。

在这里边需要保证son[i]在i之前更新,所以需要得到拓扑序。

然后大爷说会卡常?这里orz hzwer,对dis排序即可得到拓扑序,而且可以使用基数排序,详见代码。

最后求一下和,dfs一遍就好了,类似于二(十六)分。

#include <cstdio>
#include <cstring>
#include <algorithm>
#define N 1000010
using namespace std;
int n , opt , next[N][26] , fa[N] , dis[N] , last = 1 , tot = 1 , v[N] , q[N] , cnt[N] , sum[N];
char str[N];
void ins(int c)
{
int p = last , np = last = ++tot;
dis[np] = dis[p] + 1 , cnt[np] = 1;
while(p && !next[p][c]) next[p][c] = np , p = fa[p];
if(!p) fa[np] = 1;
else
{
int q = next[p][c];
if(dis[q] == dis[p] + 1) fa[np] = q;
else
{
int nq = ++tot;
memcpy(next[nq] , next[q] , sizeof(next[q])) , dis[nq] = dis[p] + 1 , fa[nq] = fa[q] , fa[np] = fa[q] = nq;
while(p && next[p][c] == q) next[p][c] = nq , p = fa[p];
}
}
}
void init()
{
int i , j , t;
for(i = 1 ; i <= tot ; i ++ ) v[dis[i]] ++ ;
for(i = 1 ; i <= n ; i ++ ) v[i] += v[i - 1];
for(i = tot ; i ; i -- ) q[v[dis[i]] -- ] = i;
for(i = tot ; i ; i -- )
{
t = q[i];
if(opt) cnt[fa[t]] += cnt[t];
else cnt[t] = 1;
}
cnt[1] = 0;
for(i = tot ; i ; i -- )
{
t = q[i] , sum[t] = cnt[t];
for(j = 0 ; j < 26 ; j ++ )
sum[t] += sum[next[t][j]];
}
}
void query(int p , int k)
{
if(k <= cnt[p]) return;
k -= cnt[p];
int i;
for(i = 0 ; i < 26 ; i ++ )
{
if(next[p][i])
{
if(k <= sum[next[p][i]])
{
putchar(i + 'a') , query(next[p][i] , k);
return;
}
k -= sum[next[p][i]];
}
}
}
int main()
{
int k , i;
scanf("%s%d%d" , str + 1 , &opt , &k) , n = strlen(str + 1);
for(i = 1 ; i <= n ; i ++ ) ins(str[i] - 'a');
init();
if(k > sum[1]) printf("-1");
else query(1 , k);
return 0;
}

【bzoj3998】[TJOI2015]弦论 后缀自动机+dp的更多相关文章

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

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

  2. [bzoj3998][TJOI2015]弦论-后缀自动机

    Brief Description 给定一个字符串, 您需要求出他的严格k小子串或非严格k小子串. Algorithm Design 考察使用后缀自动机. 首先原串建SAM, 然后如果考察每个状态代表 ...

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

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

  4. BZOJ 3998 TJOI2015 弦论 后缀自动机+DAG上的dp

    题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=3998 题意概述:对于一个给定长度为N的字符串,求它的第K小子串是什么,T为0则表示不同位置 ...

  5. 【BZOJ-3998】弦论 后缀自动机

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

  6. BZOJ 3998: [TJOI2015]弦论 后缀自动机 后缀自动机求第k小子串

    http://www.lydsy.com/JudgeOnline/problem.php?id=3998 后缀自动机应用的一个模板?需要对len进行一个排序之后再统计每个出现的数量,维护的是以该字符串 ...

  7. BZOJ 3998 [TJOI2015]弦论 ——后缀自动机

    直接构建后缀自动机. 然后. 然后只需要再后缀自动机的go树上类似二分的方法进行查找即可,实际上是“26分”. 然后遇到了处理right集合的问题,然后觉得在go和parent树上上传都是可以的,毕竟 ...

  8. [TJOI2015]弦论(后缀自动机)

    /* 一道在树上乱搞的题目 建立出parent树来, 然后就能搞出每个节点往后能扩展出几个串, 至于位置不同算同一个的话就强制让right集合大小为1即可 然后在树上类比权值线段树找第k大26分统计一 ...

  9. BZOJ.3998.[TJOI2015]弦论(后缀自动机)

    题目链接 \(Description\) 给定字符串S,求其第K小子串.(若T=0,不同位置的相同子串算1个:否则算作多个) \(Solution\) 建SAM,处理出对于每个节点,它和它的所有后继包 ...

随机推荐

  1. mongodb索引 全文索引使用限制

    全文索引非常强大,但是同样存在很多限制,我们来看以下去全文索引的使用限制: 1.每次查询,只能指定一个$text查询 2.$text查询不能出现在$nor查询中 之前没有接触过$nor查询,$nor查 ...

  2. Linux 下MySQL数据库配置远程访问

    1. mysql -u root -p 第一次直接回车跳过密码 2. use mysql; 3.执行授权命令 GRANT ALL PRIVILEGES ON *.* TO 'root'@'%' IDE ...

  3. vs code vim

    很多初学者启动vim后,不知道怎么输入字符:按了半天字母,结果屏幕还是空的. vim和记事本或WORD不一样,不是一打开后就可以输入文字,此时它处于正常模式. vim一共有4个模式: 正常模式 (No ...

  4. WP Mail SMTP插件解决Contact Form 7表单提交失败问题

    WP Mail SMTP插件解决Contact Form 7表单提交失败问题 WP Mail SMTP是一款非常优秀的解决WordPress主机因为不支持或者是禁用了mail()函数,导致无法实现在线 ...

  5. nginx反向代理与正向代理的区别

    http://blog.csdn.net/m13666368773/article/details/8060481

  6. 去除select下拉框默认样式

    去除select下拉框默认样式 select { /*Chrome和Firefox里面的边框是不一样的,所以复写了一下*/ border: solid 1px #; /*很关键:将默认的select选 ...

  7. mysql 复制一列到另一列

    https://www.cnblogs.com/clphp/p/6251469.html

  8. 第7章 数据库访问与ORM 慕课网微信小程序开发学习笔记

    第7章 数据库访问与ORM https://coding.imooc.com/learn/list/97.html 目录: 7-1 数据库操作三种方式之原生SQL 19:09 7-2 从一个错误了解E ...

  9. oracle redo 重做日志文件

    以下易容翻译自oracle dba官方文档,不足之处还望指出. 管理重做日志文件 学习目标:1.解释重做日志文件的目的2.描述重做日志文件的结构3.学会控制日志切换与检查点4.多元化管理重做日志文件5 ...

  10. Linux命令之---pwd

    命令简介 Linux中用 pwd 命令用来查看”当前工作目录“的完整路径. 命令格式 pwd [选项] 命令功能和参数 功能:查看”当前工作目录“的完整路径:参数:一般情况下不带任何参数,如果目录是链 ...