BZOJ3998 弦论 【SAM】k小子串
  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;
}
												
											BZOJ3998 弦论 【SAM】k小子串的更多相关文章
- 「BZOJ3998」[TJOI2015] 弦论(第K小子串)
		
https://www.lydsy.com/JudgeOnline/problem.php?id=3998 Description 对于一个给定长度为N的字符串,求它的第K小子串是什么. Input ...
 - [TJOI2015]弦论(第k小子串)
		
题意: 对于一个给定的长度为n的字符串,求出它的第k小子串. 有参数t,t为0则表示不同位置的相同子串算作一个,t为1则表示不同位置的相同子串算作多个. 题解: 首先,因为t的原因,后缀数组较难实现, ...
 - HDU 5008 求第k小子串
		
本题要求第k小的distinct子串,可以根据height数组,二分出这个第k小子串所在后缀的位置信息.由于题目要求子串起始下标尽可能小.所以再在rank数组中,二分出与当前后缀LCP大于等于所求子串 ...
 - Lexicographical Substring Search (spoj7259) (sam(后缀自动机)+第k小子串)
		
Little Daniel loves to play with strings! He always finds different ways to have fun with strings! K ...
 - SPOJ SUBLEX 求第k小子串
		
题目大意: 对于一个给定字符串,找到其所有不同的子串中排第k小的子串 先构建后缀自动机,然后我们可以将整个后缀自动机看做是一个DAG图,那么我们先进行拓扑排序得到 *b[N] 对于每个节点记录一个sc ...
 - k小子串 SPOJ - SUBLEX 2
		
题意: 求字典序第K大的子串 题解: 先求出后缀自动机对应节点 // 该节点后面所形成的自字符串的总数 然后直接模拟即可 #include <set> #include <map&g ...
 - BZOJ 3998: [TJOI2015]弦论 后缀自动机 后缀自动机求第k小子串
		
http://www.lydsy.com/JudgeOnline/problem.php?id=3998 后缀自动机应用的一个模板?需要对len进行一个排序之后再统计每个出现的数量,维护的是以该字符串 ...
 - 【BZOJ3998】弦论 [SAM]
		
弦论 Time Limit: 10 Sec Memory Limit: 256 MB[Submit][Status][Discuss] Description 对于一个给定长度为N的字符串,求它的第 ...
 - BZOJ3998:[TJOI2015]弦论(SAM)
		
Description 对于一个给定长度为N的字符串,求它的第K小子串是什么. Input 第一行是一个仅由小写英文字母构成的字符串S 第二行为两个整数T和K,T为0则表示不同位置的相同子串算作一个. ...
 
随机推荐
- 利用css和jquery制成弹幕
			
1.首先上图看下效果 2.废话不多说,直接上代码 1>html代码 <div class="barrage"> <div class="scree ...
 - python学习笔记 | strftime()格式化输出时间
			
time模块 import time t = time.strftime("%Y-%m-%d %H:%M:%S") print(t) datetime模块 import datet ...
 - 关于 percona monitoring plugins插件报slave is stoped on ip地址
			
思路:肯定是某个item触发了触发器 去看触发器,找到 slave is stoped,如下图 看到键是mysql.running-slave ,然后去定义key的文件中查看该键对应的脚本,修改脚本. ...
 - 【Java】单例模式(Singleton)
			
重新搞一波 复习巩固 简单记录 慕课网 Java工程师 文章目录 单例概述 设计模式 单例模式(Singleton) 参考资料 单例概述 Singleton Pattern 单例模式是Java中最简单 ...
 - 【Java】面向对象
			
重新搞一波 复习巩固 简单记录 慕课网 imooc Java 零基础入门-Java面向对象-面向对象 都是视频课件里的. 文章目录 面向对象 什么是对象 什么是面向对象 类 什么是对象的属性和方法 类 ...
 - 【linux】系统编程-7-网络编程
			
目录 前言 10. 网络编程 10.1 简要网络知识 10.2 IP协议 10.2.1 IP地址编址 10.2.2 特殊IP地址 10.2.1 首限广播地址 10.2.2 直接广播地址 10.2.3 ...
 - 06--Docker自定义镜像Tomcat9
			
1. 创建目录 /zhengcj/mydockerfile/tomcat9 2.将jdk和tomcat的安装包拷贝到tomcat9下 3.在tomcat9目录下创建Dockerfile文件,并写以下命 ...
 - java 记录数据持续变化时间
			
1.需求:获取count为null和不为null的持续变化 [{count=0, time=0}, {count=10, time=1000}, {count=20, time=2000}, {cou ...
 - 如何在C#中使用MSMQ
			
MSMQ (Microsoft消息队列)是Windows中默认可用的消息队列.作为跨计算机系统发送和接收消息的可靠方法,MSMQ提供了一个可伸缩.线程安全.简单和使用方便的队列,同时为你提供了在Win ...
 - 试玩 GOWOG ,初探 OpenAI(使用 NeuroEvolution 神经进化)与 Golang 多人在线游戏开发
			
GOWOG: 原项目:https://github.com/giongto35/gowog 我调整过的:https://github.com/Kirk-Wang/gowog GOWOG 是一款迷你的, ...