bzoj 2998 第k小字串
这道题用后缀数组貌似会T。
后缀自动机做法:
t==0:第k小的本质不同字串
首先把后缀自动机建出来,我们会得到一个DAG,并且只存在一个点入度为0(我们称之为根),可以证明字符串的任意一个本质不同的子串(不包括空串)与该自动机上一条起点为根的长度(路径边数)大于0的路径一一对应。所以我们就可以进行DP了,dp[u]表示以u为起点的串的个数,然后有点像在BST中找第k小的思想。
t==1:第k小的普通字串(不同位置但本质相同的要区分)
还是要dp,我yy的一个状态含义是:dp[u]表示,u节点的对应的后缀(right集合中每个位置对应一个后缀)的所有前缀的个数(空串也是前缀,并且不同位置的空串相互区分)。
这样,我们就默认一个长度为n的字符串有(n+1)*(n+2)/2个子串(包括n+1个空串)。
/**************************************************************
Problem: 3998
User: idy002
Language: C++
Result: Accepted
Time:9736 ms
Memory:134596 kb
****************************************************************/ #include <cstdio>
#include <cstring>
#define N 1000010 typedef long long dnt; int n, k, t;
int son[N][], val[N], pnt[N], rsiz[N], ntot, last;
int idgr[N], stk[N], qu[N], bg, ed, top;
dnt dp[N];
char str[N]; void init() {
ntot = ;
pnt[] = -;
}
void append( int c ) {
int p = last;
int np = ++ntot;
val[np] = val[last]+;
while( ~p && !son[p][c] )
son[p][c]=np,p=pnt[p];
if( p==- ) {
pnt[np] = ;
} else {
int q = son[p][c];
if( val[q]==val[p]+ ) {
pnt[np] = q;
} else {
int nq = ++ntot;
memcpy( son[nq], son[q], sizeof(son[nq]) );
val[nq] = val[p]+;
rsiz[nq] = rsiz[q];
pnt[nq] = pnt[q];
pnt[q] = pnt[np] = nq;
while( ~p && son[p][c]==q ) son[p][c]=nq,p=pnt[p];
}
}
last = np;
while( ~np ) {
rsiz[np]++;
np = pnt[np];
}
}
void print() {
for( int u=; u<=ntot; u++ ) {
fprintf( stderr, "%d(dp[%d]=%lld rsiz[%d]=%d): ", u, u, dp[u], u, rsiz[u] );
for( int c=; c<; c++ ) {
int v=son[u][c];
if( !v ) continue;
fprintf( stderr, "%c,%d ", c+'a', v );
}
fprintf( stderr, "\n" );
}
}
void make_topo() {
for( int u=; u<=ntot; u++ ) {
for( int c=; c<; c++ ) {
int v=son[u][c];
if( !v ) continue;
idgr[v]++;
}
}
top = ;
for( int u=; u<=ntot; u++ )
if( idgr[u]== )
stk[++top] = u;
bg = , ed = ;
while( top ) {
int u=stk[top--];
qu[++ed] = u;
for( int c=; c<; c++ ) {
int v=son[u][c];
if( !v ) continue;
idgr[v]--;
if( idgr[v]== )
stk[++top] = v;
}
}
}
void dodp( int s ) {
make_topo();
rsiz[s] = ;
if( t== )
for( int i=; i<=ed; i++ )
rsiz[qu[i]] = ;
for( int i=ed; i>=; i-- ) {
int u=qu[i];
dp[u] = rsiz[u];
for( int c=; c<; c++ ) {
int v=son[u][c];
if( !v ) continue;
dp[u] += dp[v];
}
}
if( dp[]<k ) {
printf( "-1\n" );
return;
}
int u = ;
int kth = k;
while() {
if( kth<=rsiz[u] ) {
printf( "\n" );
return;
} else kth-=rsiz[u];
for( int c=; c<; c++ ) {
int v=son[u][c];
if( !v ) continue;
if( dp[v]>=kth ) {
u = v;
printf( "%c", c+'a' );
break;
} else {
kth -= dp[v];
}
}
}
}
int main() {
scanf( "%s", str );
scanf( "%d%d", &t, &k );
init();
for( int i=; str[i]; i++ )
append( str[i]-'a' );
dodp();
// print();
}
bzoj 2998 第k小字串的更多相关文章
- [bzoj P4504] K个串
[bzoj P4504] K个串 [题目描述] 兔子们在玩k个串的游戏.首先,它们拿出了一个长度为n的数字序列,选出其中的一个连续子串,然后统计其子串中所有数字之和(注意这里重复出现的数字只被统计一次 ...
- bzoj : 4504: K个串 区间修改主席树
4504: K个串 Time Limit: 20 Sec Memory Limit: 512 MBSubmit: 268 Solved: 110[Submit][Status][Discuss] ...
- bzoj 4504: K个串 可持久化线段树+堆
题目: Description 兔子们在玩k个串的游戏.首先,它们拿出了一个长度为n的数字序列,选出其中的一 个连续子串,然后统计其子串中所有数字之和(注意这里重复出现的数字只被统计一次). 兔子们想 ...
- bzoj4504 k个串 kstring 可持久化线段树 (标记永久化)
[fjwc2015]k个串 kstring [题目描述] 兔子们在玩k个串的游戏.首先,它们拿出了一个长度为n的数字序列,选出其中的一个连续子串,然后统计其子串中所有数字之和(注意这里重复出现的数字只 ...
- 数据结构(主席树):COGS 2213. K个串
2213. K个串 ★★★★ 输入文件:bzoj_4504.in 输出文件:bzoj_4504.out 简单对比时间限制:20 s 内存限制:512 MB [题目描述] 兔子们在玩k个 ...
- 问题 K: 周期串plus
问题 K: 周期串plus 时间限制: 1 Sec 内存限制: 128 MB提交: 682 解决: 237[提交] [状态] [命题人:外部导入] 题目描述 如果一个字符串可以由某个长度为k的字符 ...
- hiho#1449 重复旋律6 求长度为k的串最大次数 后缀自动机
题目传送门 题目大意:求长度为k的串的最大次数,把k从1到length的所有答案全部输出. 思路: 这道题放在$SAM$里就是求长度$k$对应的所有$right$集中最大的大小. 我们以$aabab$ ...
- 【BZOJ4504】K个串 可持久化线段树+堆
[BZOJ4504]K个串 Description 兔子们在玩k个串的游戏.首先,它们拿出了一个长度为n的数字序列,选出其中的一个连续子串,然后统计其子串中所有数字之和(注意这里重复出现的数字只被统计 ...
- BZOJ 4504: K个串
题目大意: 求一个序列的第k大的子串和. 题解: 对于一个右端点找最优的左端点,扔进堆里. 每次取堆顶,将这个右端点可以选择的左端点的区间分成两段,扔进堆里,重复k次. 现在需要对于一个固定的右端点, ...
随机推荐
- Flip Bits
Determine the number of bits required to flip if you want to convert integer n to integer m. Notice ...
- php中heredoc的使用方法
Heredoc技术,在正规的PHP文档中和技术书籍中一般没有详细讲述,只是提到了这是一种Perl风格的字符串输出技术.但是现在的一些论坛程序,和部分文章系统,都巧妙的使用heredoc技术,来部分的实 ...
- [HBase] 服务端RPC机制及代码梳理
基于版本:CDH5.4.2 上述版本较老,但是目前生产上是使用这个版本,所以以此为例. 1. 概要 说明: 客户端API发送的请求将会被RPCServer的Listener线程监听到. Listene ...
- 10 The Go Programming Language Specification go语言规范 重点
The Go Programming Language Specification go语言规范 Version of May 9, 2018 Introduction 介绍 Notation 符号 ...
- TCP协议端口状态说明:CLOSE-WAIT、TIME-WAIT 、LISTENING、SYN_SENT、ESTABLISHED、LAST-ACK ...
了解TCP协议端口的连接状态,对排除和定位网络或系统故障会有很大帮助,因此了解一下是有必要的: 一.LISTENING 提供某种服务,侦听远方TCP端口的连接请求,当提供的服务没有被连接时,处于LI ...
- 基于timestamp和nonce的防止重放攻击方案
参考:http://blog.csdn.net/koastal/article/details/53456696
- elasticsearch学习笔记--原理介绍
前言:上一篇中我们对ES有了一个比较大概的概念,知道它是什么,干什么用的,今天给大家主要讲一下他的工作原理 介绍:ElasticSearch是一个基于Lucene的搜索服务器.它提供了一个分布式多用户 ...
- B树 B+树 红黑树
B-Tree(B树) 具体讲解之前,有一点,再次强调下:B-树,即为B树.因为B树的原英文名称为B-tree,而国内很多人喜欢把B-tree译作B-树,其实,这是个非常不好的直译,很容易让人产生误解. ...
- 利用sys.dm_db_index_physical_stats查看索引碎片等数据
我们都知道,提高sql server的数据查询速度,最有效的方法,就是为表创建索引,而索引在对数据进行新增,删除,修改的时候,会产生索引碎片,索引碎片多了,就需要重新组织或重新生成索引,以达到索引的最 ...
- Mac OS 下安装mysqlclient报“mysql_config not found”的解决
如问题所示,应该是你没有将mysql_config所在文件夹加入系统的PATH路径,解决方案下: 1.第一步找到你的mysql_config所在位置 1.1. 如果是直接安装mysql,所在位置应该是 ...