SPOJ.com - Problem SUBLEX

  这么裸的一个SAM,放在了死破OJ上面就是个坑。

注意用SAM做的时候输出要用一个数组存下来,然后再puts,不然一个一个字符输出会更慢。

还有一个就是不要多数据输入,估计最后多了几个没用的数字,反正我这么做一直无端端的RE。(就这样浪费了我一天好么!出数据的人这么不负责!)

最后就是,第k大的k是会超过子串数的。(这什么脑残配置?)

  综上,这题除了坑就是坑。

代码如下:

 #include <bits/stdc++.h>
using namespace std; const int N = ;
const int LAST = ;
const int K = ; struct Node {
Node *nx[K], *fail;
int dist;
long long sub; void Clear(const int d = ) {
memset(nx, , sizeof nx);
fail = ;
dist = d;
sub = ;
}
} ; struct SAM {
Node node[N << ];
Node *root, *last;
int ttNode; Node *Mem(const int d = ) {
Node *temp = node + ttNode++; temp->Clear(d); return temp;
} void Clear() {
ttNode = ;
root = last = Mem();
} void Expand(const char c) {
const int idx = c - 'a';
Node *p = last, *np = Mem(p->dist + ); for ( ; p && p->nx[idx] == ; p = p->fail) {
p->nx[idx] = np;
}
if (p) {
Node *q = p->nx[idx]; if (p->dist + != q->dist) {
Node *nq = Mem(); *nq = *q;
nq->dist = p->dist + ;
q->fail = np->fail = nq;
for ( ; p && p->nx[idx] == q; p = p->fail) {
p->nx[idx] = nq;
}
} else {
np->fail = q;
}
} else {
np->fail = root;
}
last = np;
} int dist[N << ];
Node *ptr[N << ]; void GetSub() {
memset(dist, , sizeof dist);
for (int i = ; i < ttNode; ++i) {
++dist[node[i].dist];
}
for (int i = ; i < ttNode; ++i) {
dist[i] += dist[i - ];
}
for (int i = ; i < ttNode; ++i) {
ptr[--dist[node[i].dist]] = node + i;
}
for (int i = ttNode - ; i >= ; --i) {
Node *p = ptr[i]; p->sub = ;
for (int j = ; j < K; ++j) {
if (p->nx[j]) {
p->sub += p->nx[j]->sub;
}
}
}
--node[].sub;
//for (int i = 0; i < ttNode; ++i) { cout << node[i].dist << ' '; } cout << endl;
//for (int i = 0; i < ttNode; ++i) { cout << node[i].sub << ' '; } cout << endl;
//for (int i = 0; i < ttNode; ++i) { cout << i << ": "; for (int j = 0; j < K; ++j) { cout << (node[i].nx[j] ? node[i].nx[j] - node : -1) << ' '; } cout << endl; }
}
} sam; char s[N], answer[N]; void Generate(char *const s) {
srand(time());
for (int i = ; i < LAST; ++i) {
s[i] = rand() % + 'a';
}
s[LAST] = ;
} int Run() {
//while (~scanf("%s", s)) {
//while (1) {
//Generate(s);
scanf("%s", s);
sam.Clear();
for (int i = ; s[i]; ++i) {
sam.Expand(s[i]);
}
sam.GetSub();
//cout << sam.root->sub << endl;
//if (sam.ttNode >= (N << 1)) { puts("???"); while (1) ; } int n, k; scanf("%d", &n);
while (n--) {
Node *p = sam.root;
int pos = ; scanf("%d", &k);
//if (k > sam.root->sub) { puts("..."); while (1) ; }
k = (k - ) % sam.root->sub + ;
while (k > ) {
for (int i = ; i < K; ++i) {
if (p->nx[i] == ) {
continue;
} const int cnt = p->nx[i]->sub; if (cnt >= k) {
//putchar('a' + i);
answer[pos++] = 'a' + i;
p = p->nx[i];
--k;
break;
} else {
k -= cnt;
}
}
}
answer[pos] = ;
puts(answer);
//puts("");
}
//} return ;
} int main() {
//ios::sync_with_stdio(0);
return Run();
}

UPD:还有更坑的,我开99999 * 2的SAM节点数是会TLE的,开222222 * 2才AC。我猜肯定是新增的数据各种问题,数据不在范围内了。

——written by LyonLys

spoj SUBLEX (Lexicographical Substring Search) RE的欢迎来看看的更多相关文章

  1. SPOJ SUBLEX - Lexicographical Substring Search 后缀自动机 / 后缀数组

    SUBLEX - Lexicographical Substring Search Little Daniel loves to play with strings! He always finds ...

  2. SPOJ SUBLEX Lexicographical Substring Search - 后缀数组

    题目传送门 传送门I 传送门II 题目大意 给定一个字符串,多次询问它的第$k$大本质不同的子串,输出它. 考虑后缀Trie.依次考虑每个后缀新增的本质不同的子串个数,显然,它是$n - sa[i] ...

  3. Spoj SUBLEX - Lexicographical Substring Search

    Dicription Little Daniel loves to play with strings! He always finds different ways to have fun with ...

  4. spoj SUBLEX - Lexicographical Substring Search【SAM】

    先求出SAM,然后考虑定义,点u是一个right集合,代表了长为dis[son]+1~dis[u]的串,然后根据有向边转移是添加一个字符,所以可以根据这个预处理出si[u],表示串u后加字符能有几个本 ...

  5. spoj 7258 Lexicographical Substring Search (后缀自动机)

    spoj 7258 Lexicographical Substring Search (后缀自动机) 题意:给出一个字符串,长度为90000.询问q次,每次回答一个k,求字典序第k小的子串. 解题思路 ...

  6. SPOJ:SUBLEX - Lexicographical Substring Search

    题面 第一行给定主串\((len<=90000)\) 第二行给定询问个数\(T<=500\) 随后给出\(T\)行\(T\)个询问,每次询问排名第\(k\)小的串,范围在\(int\)内 ...

  7. SPOJ 7258 Lexicographical Substring Search(后缀自动机)

    [题目链接] http://www.spoj.com/problems/SUBLEX/ [题目大意] 给出一个字符串,求其字典序排名第k的子串 [题解] 求出sam上每个节点被经过的次数,然后采用权值 ...

  8. ●SPOJ 7258 Lexicographical Substring Search

    题链: http://www.spoj.com/problems/SUBLEX/题解: 后缀自动机. 首先,因为相同的子串都被存在了自动机的同一个状态里面,所以这就很自然的避免了重复子串的问题. 然后 ...

  9. SPOJ 7258 Lexicographical Substring Search

    Little Daniel loves to play with strings! He always finds different ways to have fun with strings! K ...

随机推荐

  1. Mathtype部分数学符号不能显示,只能显示方框时的解决办法

    解决方法:打开C:\WINDOWS\Fonts,若里面有MT Extra(TrueType)字体或其快捷方式,则将其删除,再把MathType安装目录下\MathType 6.0\Fonts\True ...

  2. Oracle基础知识:DECODE、NVL

    select 1 from PMADW.GET_WX_DATAPUSH_NEW_CHECK A INNER JOIN PMADW.V_EXCEPTION_QTY_MAIN B on DECODE( A ...

  3. Openlayers3 WebGis二次开发包实例

    <%@ Page Language="C#" AutoEventWireup="true" CodeBehind="index.aspx.cs& ...

  4. Python 爬取高清桌面壁纸

    今天写了一个脚本用来爬取ZOL桌面壁纸网站的高清图片: 链接:http://desk.zol.com.cn/1920x1080/ 本程序只爬了美女板块的图片,若要下载其他板块,只需修改程序中的&quo ...

  5. Java 类与类之间的调用

    方法1. 新建一个类. 然后在调用类中先进行被调用类实例化,然后通过实例化的对象访问. 例如: //先定义一个类 import static java.lang.System.out; public ...

  6. Neo4j系列-简介及应用场景

    1.什么是Neo4j? Neo4j是一个高性能的NOSQL图形数据库,它将结构化数据存储在网络上而不是表中.它是一个嵌入式的.基于磁盘的.具备完全的事务特性的Java持久化引擎,但是它将结构化数据存储 ...

  7. Vue.之.路由跳转

    Vue.之.路由跳转 在进行项目开发的过程中,需要使用路由进行跳转.如下: // 不带有参数,在页面上跳转到别的页面 1. this.$router.push('/login/init');  // ...

  8. GYM 101981E(开关反转性质)

    要点 做法是删去连续的k个0或k个1,连消.消消乐的那种,网上博主用个栈\(O(n)\)就很优秀地操作了这个过程 原因是有性质:比如k=3,101000贪心地翻就能翻成000101,所以连续的k个可以 ...

  9. windows无法启动MySQL服务报错1067的解决方法是怎样?

    方法一: 1.打开my.ini文件,找到default-storage-engine=InnoDB这一行,把它改成default-storage-engine=MyISAM.2.删除在MySQL安装目 ...

  10. 模拟21 题解(waiting)

    留坑待填 效率!!! 题还没改Oh,NO!!!