博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
bzoj 2998 第k小字串
阅读量:5273 次
发布时间:2019-06-14

本文共 3643 字,大约阅读时间需要 12 分钟。

 

这道题用后缀数组貌似会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个空串)。

 

1 /**************************************************************  2     Problem: 3998  3     User: idy002  4     Language: C++  5     Result: Accepted  6     Time:9736 ms  7     Memory:134596 kb  8 ****************************************************************/  9   10 #include 
11 #include
12 #define N 1000010 13 14 typedef long long dnt; 15 16 int n, k, t; 17 int son[N][26], val[N], pnt[N], rsiz[N], ntot, last; 18 int idgr[N], stk[N], qu[N], bg, ed, top; 19 dnt dp[N]; 20 char str[N]; 21 22 void init() { 23 ntot = 0; 24 pnt[0] = -1; 25 } 26 void append( int c ) { 27 int p = last; 28 int np = ++ntot; 29 val[np] = val[last]+1; 30 while( ~p && !son[p][c] ) 31 son[p][c]=np,p=pnt[p]; 32 if( p==-1 ) { 33 pnt[np] = 0; 34 } else { 35 int q = son[p][c]; 36 if( val[q]==val[p]+1 ) { 37 pnt[np] = q; 38 } else { 39 int nq = ++ntot; 40 memcpy( son[nq], son[q], sizeof(son[nq]) ); 41 val[nq] = val[p]+1; 42 rsiz[nq] = rsiz[q]; 43 pnt[nq] = pnt[q]; 44 pnt[q] = pnt[np] = nq; 45 while( ~p && son[p][c]==q ) son[p][c]=nq,p=pnt[p]; 46 } 47 } 48 last = np; 49 while( ~np ) { 50 rsiz[np]++; 51 np = pnt[np]; 52 } 53 } 54 void print() { 55 for( int u=0; u<=ntot; u++ ) { 56 fprintf( stderr, "%d(dp[%d]=%lld rsiz[%d]=%d): ", u, u, dp[u], u, rsiz[u] ); 57 for( int c=0; c<26; c++ ) { 58 int v=son[u][c]; 59 if( !v ) continue; 60 fprintf( stderr, "%c,%d ", c+'a', v ); 61 } 62 fprintf( stderr, "\n" ); 63 } 64 } 65 void make_topo() { 66 for( int u=0; u<=ntot; u++ ) { 67 for( int c=0; c<26; c++ ) { 68 int v=son[u][c]; 69 if( !v ) continue; 70 idgr[v]++; 71 } 72 } 73 top = 0; 74 for( int u=0; u<=ntot; u++ ) 75 if( idgr[u]==0 ) 76 stk[++top] = u; 77 bg = 1, ed = 0; 78 while( top ) { 79 int u=stk[top--]; 80 qu[++ed] = u; 81 for( int c=0; c<26; c++ ) { 82 int v=son[u][c]; 83 if( !v ) continue; 84 idgr[v]--; 85 if( idgr[v]==0 ) 86 stk[++top] = v; 87 } 88 } 89 } 90 void dodp( int s ) { 91 make_topo(); 92 rsiz[s] = 0; 93 if( t==0 ) 94 for( int i=2; i<=ed; i++ ) 95 rsiz[qu[i]] = 1; 96 for( int i=ed; i>=1; i-- ) { 97 int u=qu[i]; 98 dp[u] = rsiz[u]; 99 for( int c=0; c<26; c++ ) {100 int v=son[u][c];101 if( !v ) continue;102 dp[u] += dp[v];103 }104 }105 if( dp[0]
=kth ) {120 u = v;121 printf( "%c", c+'a' );122 break;123 } else {124 kth -= dp[v];125 }126 }127 }128 }129 int main() {130 scanf( "%s", str );131 scanf( "%d%d", &t, &k );132 init();133 for( int i=0; str[i]; i++ )134 append( str[i]-'a' );135 dodp(0);136 // print();137 }
View Code

 

转载于:https://www.cnblogs.com/idy002/p/4516574.html

你可能感兴趣的文章
验证组件FluentValidation的使用示例
查看>>
0320-学习进度条
查看>>
解决windows系统的oracle数据库不能启动ora-00119和ora-00130的问题
查看>>
ip相关问题解答
查看>>
MetaWeblog API Test
查看>>
反弹SHELL
查看>>
关闭Chrome浏览器的自动更新和升级提示
查看>>
移动、尺寸改变
查看>>
微信智能开放平台
查看>>
c# 文件笔记
查看>>
第一页 - 工具的使用(webstorm)
查看>>
类和结构
查看>>
CSS3选择器(二)之属性选择器
查看>>
adidas crazylight 2018 performance analysis review
查看>>
typeset shell 用法
查看>>
python 之 循环语句
查看>>
心得25--JDK新特性9-泛型1-加深介绍
查看>>
[转]ceph网络通信模块_以monitor模块为例
查看>>
HDOJ 1754 I Hate It(线段树基本操作)
查看>>
latex tree
查看>>