Lexicographical Substring Search SPOJ - SUBLEX (后缀自动机)
Lexicographical Substrings Search
\]
题意
给出一个字符串,求出这个字符串上字典序第 \(k\) 小的子串。
思路
先对给出的字符串构建后缀自动机,因为后缀自动机上从根节点走到任意节点都是原串的一个子串,所以我们可以 \(dfs\) 求出节点 \(i\) 往后存在多少个子串。
对于查询第 \(k\) 小的子串时,在用一个 \(dfs\) 来求,对于当前节点\(u\), 从\(1-26\) 枚举下一步的方案 \(v\),如果从 \(v\) 往后的子串比 \(k\) 少,那么不用往下走,直接 \(k-=cnt[v]\)。否则往下走一步,让 \(k--\)。如此一直走到 \(k=0\) 为止。
/***************************************************************
> File Name : a.cpp
> Author : Jiaaaaaaaqi
> Created Time : 2019年05月22日 星期三 17时06分12秒
***************************************************************/
#include <map>
#include <set>
#include <list>
#include <ctime>
#include <cmath>
#include <stack>
#include <queue>
#include <cfloat>
#include <string>
#include <vector>
#include <cstdio>
#include <bitset>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
#define lowbit(x) x & (-x)
#define mes(a, b) memset(a, b, sizeof a)
#define fi first
#define se second
#define pii pair<int, int>
typedef unsigned long long int ull;
typedef long long int ll;
const int maxn = 1e5 + 10;
const int maxm = 1e5 + 10;
const ll mod = 1e9 + 7;
const ll INF = 1e18 + 100;
const int inf = 0x3f3f3f3f;
const double pi = acos(-1.0);
const double eps = 1e-8;
using namespace std;
int n, m;
int cas, tol, T;
struct SAM {
struct Node{
int next[27];
int fa, len;
void init() {
mes(next, 0);
len = fa = 0;
}
} node[maxn<<1];
int sz, last;
int cnt[maxn<<1];
void init() {
sz = last = 1;
node[sz].init();
mes(cnt, 0);
}
void insert(int k) {
int p = last, np = last = ++sz;
node[np].init();
node[np].len = node[p].len+1;
for(; p&&!node[p].next[k]; p=node[p].fa)
node[p].next[k] = np;
if(p==0) {
node[np].fa = 1;
} else {
int q = node[p].next[k];
if(node[q].len == node[p].len + 1) {
node[np].fa = q;
} else {
int nq = ++sz;
node[nq] = node[q];
node[nq].len = node[p].len + 1;
node[np].fa = node[q].fa = nq;
for(; p&&node[p].next[k]==q; p=node[p].fa)
node[p].next[k] = nq;
}
}
}
void dfs(int u) {
if(cnt[u]) return ;
cnt[u] = 1;
for(int i=1; i<=26; i++) {
int v = node[u].next[i];
if(v) {
dfs(v);
cnt[u] += cnt[v];
}
}
}
char ss[maxn];
void find(int u, int k, int len) {
if(k==0) {
ss[len] = '\0';
printf("%s\n", ss+1);
return ;
}
for(int i=1; i<=26; i++) {
int v = node[u].next[i];
if(v==0) continue;
if(cnt[v] < k) k -= cnt[v];
else {
k--;
ss[len] = 'a'+i-1;
find(v, k, len+1);
return ;
}
}
}
void solve(int k) {
find(1, k, 1);
}
} sam;
char s[maxn];
int main() {
sam.init();
scanf("%s", s+1);
int len = strlen(s+1);
for(int i=1; i<=len; i++) {
sam.insert(s[i]-'a'+1);
}
sam.dfs(1);
// for(int i=2; i<=sam.sz; i++) {
// printf("cnt[%d] = %d\n", i, sam.cnt[i]);
// }
scanf("%d", &T);
while(T--) {
scanf("%d", &m);
sam.solve(m);
}
return 0;
}
Lexicographical Substring Search SPOJ - SUBLEX (后缀自动机)的更多相关文章
- Lexicographical Substring Search SPOJ - SUBLEX (后缀数组)
Lexicographical Substrings Search \[ Time Limit: 149 ms \quad Memory Limit: 1572864 kB \] 题意 给出一个字符串 ...
- 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 后缀自动机
SPOJ - SUBLEX 思路:求第k大字串,求出sam上每个节点开始能识别多少字串,然后从起点开始跑就好啦. #include<bits/stdc++.h> #define LL lo ...
- SPOJ SUBLEX - Lexicographical Substring Search 后缀自动机 / 后缀数组
SUBLEX - Lexicographical Substring Search Little Daniel loves to play with strings! He always finds ...
- spoj 7258 Lexicographical Substring Search (后缀自动机)
spoj 7258 Lexicographical Substring Search (后缀自动机) 题意:给出一个字符串,长度为90000.询问q次,每次回答一个k,求字典序第k小的子串. 解题思路 ...
- 【SPOJ】7258. Lexicographical Substring Search(后缀自动机)
http://www.spoj.com/problems/SUBLEX/ 后缀自动机系列完成QAQ...撒花..明天or今晚写个小结? 首先得知道:后缀自动机中,root出发到任意一个状态的路径对应一 ...
- SPOJ SUBLEX 7258. Lexicographical Substring Search
看起来像是普通的SAM+dfs...但SPOJ太慢了......倒腾了一个晚上不是WA 就是RE ..... 最后换SA写了...... Lexicographical Substring Searc ...
- [SPOJ7258]Lexicographical Substring Search
[SPOJ7258]Lexicographical Substring Search 试题描述 Little Daniel loves to play with strings! He always ...
- 【SPOJ - SUBLEX】Lexicographical Substring Search 【后缀自动机+dp】
题意 给出一个字符串和q个询问,每个询问给出一个整数k,输出第k大得子串. 分析 建后缀自动机,利用匹配边来解决.设d[v]为从状态v开始有多少不同的路径.这个显然是可以递推出来的.然后对于每个询问, ...
随机推荐
- 从零开始学C语言
从零开始学C语言 @阆苑祁寒 更新时间:2019-09-13 写在前面:本文从一个初学者的角度,给出了对C语言的简单理解.如有谬误,敬请指出! Week1——基本语法 #include <std ...
- 百度前端技术学院-task1.3源代码
因为其中有图片,所以就给有图片的位置加了边框和设置了大小,这样哪怕图片不显示也可以知道在哪里. <!DOCTYPE html> <html> <head> < ...
- FusionInsight大数据开发---sorl应用开发
sorl应用开发 要求: 了解Solr应用开发适用场景 熟悉Solr应用开发流程 熟悉并使用Solr常用API 理解Collection设计基本原则 应用开发实践 Solr简介 Solr是一个高性能, ...
- java中各种常见的异常
一.各种常见的异常 在上一节中程序如果你注意留意,程序抛出的异常是:java.lang.ArithmeticException.这个异常是在lang包中已经定义的.在lang包中还定义了一些我们非常常 ...
- WPF Dispatcher使用
微软在WPF引入了Dispatcher,那么这个Dispatcher的主要作用是什么呢?Dispatcher的作用是用于管理线程工作项队列.主线程负责接收输入.处理事件.绘制屏幕等工作,这样一来,UI ...
- Python进阶----pymysql的安装与使用,mysql数据库的备份和恢复,mysql的事务和锁
Python进阶----pymysql的安装与使用,mysql数据库的备份和恢复,mysql的事务和锁 一丶安装 pip install PyMySQL 二丶pymysql连接数据库 ### 语法: ...
- EntityFramework DBContext 类动态控制 数据库连接(支持Oracle,SQL server)
public class ManagementDBContext : DbContext { public static string configString = Conf ...
- 如何将一个div盒子水平垂直都居中?
html代码如下: 固定样式: 方法一:利用定位(常用方法,推荐) .parent{ position:relative; } .child{ position:absolute; top:50%; ...
- iOS 视图调用
init-初始化程序 viewDidLoad-加载视图 viewWillAppear-UIViewController对象的视图即将加入窗口时调用: viewDidApper-UIViewContro ...
- git 自定义log
个人记录防止忘记 log别名: git config --global alias.lg=log --color --graph --pretty=format:'%Cred%h%Creset -%C ...