• spoj SUBLEX (Lexicographical Substring Search) RE的欢迎来看看


    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

  • 相关阅读:
    Android开发过程中的坑及解决方法收录(二)
    【转】Android开发之数据库SQL
    Android开发过程中的坑及解决方法收录(一)
    Android开发之基于监听的事件处理
    Android开发——导入github安卓项目源码
    Android开发之常见事件响应方式
    Android studio导入eclipse项目(亲测)
    Android开发——diglog cancel与dismiss方法区别
    Android开发——Toast知识
    android 点击返回键 以及 加载activity 生命周期 记录。。。,一目了然
  • 原文地址:https://www.cnblogs.com/LyonLys/p/spoj_sublex.html
Copyright © 2020-2023  润新知