BZOJ3998 弦论



给一个字符串,问其第\(K\)小字串是什么

两种形式

1.不同起始位置的相同串只算一次

2.不同起始位置的相同串各算一次

首先建\(SAM\)

所有串的数量就是\(SAM\)中的从起始点开始的路径数量,所以可以先在\(SAM\)上\(dp\)出来从所有节点开始的子串数量,然后递归找就好了

\(dp\)的转移为\(dp[u] = cnt[u] + \sum_{v \in children} dp[v]\)

对于第一种,每个节点的\(cnt\)为\(1\),对于第二种形式,每个节点的\(cnt\)为其\(right\)集合的大小

所以第二种情况下要计算出每个状态的\(right\)集合的大小

#include<bits/stdc++.h>
using namespace std;
const int MAXN = 1e6+7;
typedef long long int LL;
char s[MAXN];
int t,K,n;
struct SAM{
int link[MAXN],len[MAXN],ch[MAXN][26],last,tot;
LL f[MAXN],cnt[MAXN];
vector<int> G[MAXN];
SAM(){ link[0] = -1; last = tot = len[0] = 0; }
void extend(char chr){
int c = chr - 'a';
int np = ++tot, p = last;
cnt[np] = 1; len[np] = len[last] + 1;
while(p!=-1 and !ch[p][c]){
ch[p][c] = np;
p = link[p];
}
if(p==-1) link[np] = 0;
else{
int q = ch[p][c];
if(len[p]+1==len[q]) link[np] = q;
else{
int clone = ++tot;
link[clone] = link[q];
for(int i = 0; i < 26; i++) ch[clone][i] = ch[q][i];
len[clone] = len[p] + 1;
link[q] = link[np] = clone;
while(p!=-1 and ch[p][c]==q){
ch[p][c] = clone;
p = link[p];
}
}
}
last = np;
}
void calsubstring(int u = 0){
f[u] = cnt[u];
for(int c = 0; c < 26; c++){
if(!ch[u][c]) continue;
if(!f[ch[u][c]]) calsubstring(ch[u][c]);
f[u] += f[ch[u][c]];
}
}
void build(){ for(int i = 1; i <= tot; i++) G[link[i]].push_back(i); dfs(0); }
void dfs(int u){
for(int i = 0; i < (int)G[u].size(); i++){
int v = G[u][i];
dfs(v); cnt[u] += cnt[v];
}
}
void _kth(int u, string &str, int k){
if(k<=cnt[u]) return;
k -= cnt[u];
for(int i = 0; i < 26; i++){
if(!ch[u][i]) continue;
if(f[ch[u][i]]>=k){
str.append(1,char(i+'a'));
_kth(ch[u][i],str,k);
return;
}
else k -= f[ch[u][i]];
}
}
string kth(int k){
if(f[0]<k) return string("-1");
string str;
_kth(0,str,k);
return str;
}
}sam;
int main(){
scanf("%s %d %d",s,&t,&K);
n = strlen(s);
for(int i = 0; i < n; i++) sam.extend(s[i]);
if(t==1) sam.build();
else fill(sam.cnt,sam.cnt+MAXN,1);
sam.cnt[0] = 0;
sam.calsubstring();
printf("%s\n",sam.kth(K).c_str());
return 0;
}

最新文章

  1. .NET MVC 和 JAVA MVC有什么区别?
  2. ubuntu下安装kde Plasma
  3. .Net 执行 Oracle SQL语句时, 中文变问号
  4. JQuery Mobile + Cordova 实战一
  5. setbuf和freopen
  6. Springmvc+uploadify实现文件带进度条批量上传
  7. IAR:Error [Li005]:no definition for&quot;***&quot; 问题之连接
  8. 一个响应式数据库框架SQLBrite,完美解决数据库和UI的同步更新!
  9. 【原】1.1RDD源码解读(二)
  10. CircleImageView 圆形图片头像实现
  11. 一步一步深入spring(6)--使用基于XML配置的spring实现的AOP
  12. 【Atom】在一个中/大型项目中,那些好用而强大的atom功能
  13. 2017 ACM/ICPC Asia Regional Shenyang Online spfa+最长路
  14. 当心Azure跨区域数据传输产生额外费用
  15. mysql驱动问题
  16. React Native 填坑之神奇的报错,已解决
  17. TCP/IP及内核参数优化调优
  18. 现代 PHP 新特性 —— 生成器入门(转)
  19. mysql5.7 的 user表的密码字段从 password 变成了 authentication_string
  20. vue 父子组件

热门文章

  1. 万万没想到,JVM内存区域的面试题也可以问的这么难?
  2. 在Windows中安装MongoDB--图文并茂
  3. 天梯赛练习 L3-011 直捣黄龙 (30分) dijkstra + dfs
  4. PAT天梯赛练习 L3-003 社交集群 (30分) DFS搜索
  5. 当Django设置DEBUG为False时,发现admin和html的静态资源文件加载失败的解决办法
  6. 超过varchar定义长度
  7. 在项目中应该使用Boolean还是使用boolean?
  8. Upload - Labs (上)
  9. gears-绕过rbash
  10. RESTful风格、异常处理、Spring框架