SPOJ.com - Problem SUBLEX

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

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

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

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

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

代码如下:

  1 #include <bits/stdc++.h>
  2 using namespace std;
  3
  4 const int N = 222222;
  5 const int LAST = 90000;
  6 const int K = 26;
  7
  8 struct Node {
  9     Node *nx[K], *fail;
 10     int dist;
 11     long long sub;
 12
 13     void Clear(const int d = 0) {
 14         memset(nx, 0, sizeof nx);
 15         fail = 0;
 16         dist = d;
 17         sub = 0;
 18     }
 19 } ;
 20
 21 struct SAM {
 22     Node node[N << 1];
 23     Node *root, *last;
 24     int ttNode;
 25
 26     Node *Mem(const int d = 0) {
 27         Node *temp = node + ttNode++;
 28
 29         temp->Clear(d);
 30
 31         return temp;
 32     }
 33
 34     void Clear() {
 35         ttNode = 0;
 36         root = last = Mem();
 37     }
 38
 39     void Expand(const char c) {
 40         const int idx = c - 'a';
 41         Node *p = last, *np = Mem(p->dist + 1);
 42
 43         for ( ; p && p->nx[idx] == 0; p = p->fail) {
 44             p->nx[idx] = np;
 45         }
 46         if (p) {
 47             Node *q = p->nx[idx];
 48
 49             if (p->dist + 1 != q->dist) {
 50                 Node *nq = Mem();
 51
 52                 *nq = *q;
 53                 nq->dist = p->dist + 1;
 54                 q->fail = np->fail = nq;
 55                 for ( ; p && p->nx[idx] == q; p = p->fail) {
 56                     p->nx[idx] = nq;
 57                 }
 58             } else {
 59                 np->fail = q;
 60             }
 61         } else {
 62             np->fail = root;
 63         }
 64         last = np;
 65     }
 66
 67     int dist[N << 1];
 68     Node *ptr[N << 1];
 69
 70     void GetSub() {
 71         memset(dist, 0, sizeof dist);
 72         for (int i = 0; i < ttNode; ++i) {
 73             ++dist[node[i].dist];
 74         }
 75         for (int i = 1; i < ttNode; ++i) {
 76             dist[i] += dist[i - 1];
 77         }
 78         for (int i = 0; i < ttNode; ++i) {
 79             ptr[--dist[node[i].dist]] = node + i;
 80         }
 81         for (int i = ttNode - 1; i >= 0; --i) {
 82             Node *p = ptr[i];
 83
 84             p->sub = 1;
 85             for (int j = 0; j < K; ++j) {
 86                 if (p->nx[j]) {
 87                     p->sub += p->nx[j]->sub;
 88                 }
 89             }
 90         }
 91         --node[0].sub;
 92         //for (int i = 0; i < ttNode; ++i) { cout << node[i].dist << ' '; } cout << endl;
 93         //for (int i = 0; i < ttNode; ++i) { cout << node[i].sub << ' '; } cout << endl;
 94         //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; }
 95     }
 96 } sam;
 97
 98 char s[N], answer[N];
 99
100 void Generate(char *const s) {
101     srand(time(0));
102     for (int i = 0; i < LAST; ++i) {
103         s[i] = rand() % 26 + 'a';
104     }
105     s[LAST] = 0;
106 }
107
108 int Run() {
109     //while (~scanf("%s", s)) {
110     //while (1) {
111         //Generate(s);
112         scanf("%s", s);
113         sam.Clear();
114         for (int i = 0; s[i]; ++i) {
115             sam.Expand(s[i]);
116         }
117         sam.GetSub();
118         //cout << sam.root->sub << endl;
119         //if (sam.ttNode >= (N << 1)) { puts("???"); while (1) ; }
120
121         int n, k;
122
123         scanf("%d", &n);
124         while (n--) {
125             Node *p = sam.root;
126             int pos = 0;
127
128             scanf("%d", &k);
129             //if (k > sam.root->sub) { puts("..."); while (1) ; }
130             k = (k - 1) % sam.root->sub + 1;
131             while (k > 0) {
132                 for (int i = 0; i < K; ++i) {
133                     if (p->nx[i] == 0) {
134                         continue;
135                     }
136
137                     const int cnt = p->nx[i]->sub;
138
139                     if (cnt >= k) {
140                         //putchar('a' + i);
141                         answer[pos++] = 'a' + i;
142                         p = p->nx[i];
143                         --k;
144                         break;
145                     } else {
146                         k -= cnt;
147                     }
148                 }
149             }
150             answer[pos] = 0;
151             puts(answer);
152             //puts("");
153         }
154     //}
155
156     return 0;
157 }
158
159 int main() {
160     //ios::sync_with_stdio(0);
161     return Run();
162 }

View Code

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

——written by LyonLys

转载于:https://www.cnblogs.com/LyonLys/p/spoj_sublex.html

spoj SUBLEX (Lexicographical Substring Search) RE的欢迎来看看相关推荐

  1. SPOJ - SUBLEX Lexicographical Substring Search(后缀自动机)

    题目链接:点击查看 题目大意:给出一个字符串 s ,再给出 m 次询问,每次询问需要回答字符串中第 k 小的的子串(去重后) 题目分析:可以先对字符串 s 构造SAM,因为是去重后的子串,正好对应了S ...

  2. 【luogu SP7258】SUBLEX - Lexicographical Substring Search

    SUBLEX - Lexicographical Substring Search 题目链接:luogu SP7258 题目大意 给你一个字符串,要你求字典序第 k 大的子串. (相同的子串算只一个) ...

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

    题目链接:http://www.spoj.com/problems/SUBLEX/ 题意:给定一个字符串,每次询问第K小的串. 思路:建立自动机.cnt[p]=sigama(cnt[son[p][i] ...

  4. SPOJ7258 SUBLEX - Lexicographical Substring Search

    传送门[洛谷] 心态崩了我有妹子 靠 我写的记忆化搜索 莫名WA了 然后心态崩了 当我正要改成bfs排序的时候 我灵光一动 md我写的i=0;i<25;i++??? 然后 改过来就A掉了T^T ...

  5. SP7258 SUBLEX - Lexicographical Substring Search(后缀自动机)

    传送门 解题思路 首先建\(sam\),然后在拓扑序上\(dp\)一下,把每个点的路径数算出来,然后统计答案时就在自动机上\(dfs\)一下,仿照平衡树那样找第\(k\)小. 代码 #include& ...

  6. spoj7258 SUBLEX Lexicographical Substring Search

    http://www.elijahqi.win/archives/3001 题意翻译 给定一个字符串,求排名第k小的串 注意样例的\n是换行 输入格式: 第一行给定主串(len<=90000) ...

  7. [SPOJ7258]Lexicographical Substring Search

    [SPOJ7258]Lexicographical Substring Search 试题描述 Little Daniel loves to play with strings! He always ...

  8. 【SPOJ 7258】Lexicographical Substring Search

    http://www.spoj.com/problems/SUBLEX/ 好难啊. 建出后缀自动机,然后在后缀自动机的每个状态上记录通过这个状态能走到的不同子串的数量.该状态能走到的所有状态的f值的和 ...

  9. 【SPOJ】7258. Lexicographical Substring Search(后缀自动机)

    http://www.spoj.com/problems/SUBLEX/ 后缀自动机系列完成QAQ...撒花..明天or今晚写个小结? 首先得知道:后缀自动机中,root出发到任意一个状态的路径对应一 ...

最新文章

  1. 优达学城《DeepLearning》2-3:权重初始化
  2. mysql异常修复_MySQL错误修复:Table xx is marked as crashed and last (automatic?) repair failed...
  3. YY:马化腾的大漏招
  4. Python学习day02_数字类型 与 布尔类型 短路逻辑和运算符优先级
  5. Validator验证
  6. 让CentOS 5.3支持ntfs分区
  7. android plot,androidplot行不显示
  8. 小程序优化处理解决方案1 请求和setData
  9. Mysql 驱动包mysql-connector-java-8.0.25.jar下载
  10. MyBatis的基本增删改查及条件操作及main方法调用
  11. 光环PMP 串讲冲刺 场景题目分析
  12. c语言运算优先级口诀简单,C语言运算符优先级口诀
  13. 5年 Android 面试题
  14. MPX200 ROM DIY指南[转]
  15. L1-054 福到了 (15 分)
  16. 矢量合成和分解的法则_矢量合成和分解的方法--平行四边形法则.ppt
  17. kibana 搜索语法
  18. 《如何优化项目一》:页面缓存优化
  19. 基类与派生类对象的关系 派生类的构造函数
  20. Python 内置函数 filter()

热门文章

  1. android手机编译可运行的linux程序
  2. 为什么银行存款不能按复利计息?
  3. 月工资5000元,如何快速积累30万?
  4. PHP会话管理——Session和Cookie
  5. 64位Ubuntu kylin 16.04使用fastboot下载内核到tiny4412开发板
  6. vue 项目难点_vue项目中遇到的问题汇总
  7. 磁共振线圈分类_收藏:磁共振检查序列及临床应用总结
  8. python decorator_python 中的decorator
  9. 更新fielddata为true_线程与更新UI,细谈原理
  10. 南京师范大学874计算机答案,2017年南京师范大学电气与自动化工程学院874电路考研题库...