zoukankan      html  css  js  c++  java
  • SPOJ SUBLEX Lexicographical Substring Search

    题目传送门

      传送门I

      传送门II

    题目大意

      给定一个字符串,多次询问它的第$k$大本质不同的子串,输出它。

      考虑后缀Trie。依次考虑每个后缀新增的本质不同的子串个数,显然,它是$n - sa[i] - height[i]$。

      求出$height$数组后,求一求本质不同的子串个数的前缀和,可以对每个询问二分。

      这里可以直接离线,$O(n + m)$扫一扫就好了。

    Code

      1 /**
      2  * SPOJ
      3  * Problem#SUBLEX
      4  * Accepted
      5  * Time: 30ms
      6  * Memory: 19456k
      7  */
      8 #include <bits/stdc++.h>
      9 using namespace std;
     10 typedef bool boolean;
     11 
     12 typedef class Pair3 {
     13     public:
     14         int x, y, id;
     15 }Pair3;
     16 
     17 typedef class Query {
     18     public:
     19         int k, s, t, id;
     20 
     21         boolean operator < (Query b) const {
     22             return k < b.k;
     23         }
     24 }Query;
     25 
     26 const int N = 1e5 + 5, M = 505;
     27 
     28 int n, m;
     29 char str[N], bs[N];
     30 int rk[N << 1], sa[N], hei[N], cnt[N];
     31 Pair3 ps[N], buf[N];
     32 Query qs[M];
     33 
     34 inline void init() {
     35     scanf("%s", str + 1);
     36     n = strlen(str + 1);
     37     scanf("%d", &m);
     38     for (int i = 1; i <= m; i++)
     39         scanf("%d", &qs[i].k), qs[i].id = i;
     40 }
     41 
     42 inline void radix_sort(Pair3* x, Pair3* y) {
     43     int m = ((n > 256) ? (n) : (256));
     44     memset(cnt, 0, sizeof(int) * (m + 1));
     45     for (int i = 1; i <= n; i++)    cnt[x[i].y]++;
     46     for (int i = 1; i <= m; i++)    cnt[i] += cnt[i - 1];
     47     for (int i = 1; i <= n; i++)    y[cnt[x[i].y]--] = x[i];
     48     memset(cnt, 0, sizeof(int) *  (m + 1));
     49     for (int i = 1; i <= n; i++)    cnt[y[i].x]++;
     50     for (int i = 1; i <= m; i++)    cnt[i] += cnt[i - 1];
     51     for (int i = n; i; i--)    x[cnt[y[i].x]--] = y[i];
     52 }
     53 
     54 inline void build_sa() {
     55     for (int i = 1; i <= n; i++)
     56         rk[i] = str[i];
     57     for (int k = 1, dif = 0; k <= n; k <<= 1, dif = 0) {
     58         for (int i = 1; i <= n; i++)
     59             ps[i].x = rk[i], ps[i].y = rk[i + k], ps[i].id = i;
     60         radix_sort(ps, buf);
     61         rk[ps[1].id] = ++dif;
     62         for (int i = 2; i <= n; i++)
     63             rk[ps[i].id] = (dif += (ps[i].x != ps[i - 1].x || ps[i].y != ps[i - 1].y));
     64         if (dif == n)
     65             break;
     66     }
     67     for (int i = 1; i <= n; i++)
     68         sa[rk[i]] = i;
     69 }
     70 
     71 inline void get_height() {
     72     for (int i = 1, j, k = 0; i <= n; i++) {
     73         if (k)    k--;
     74         if (rk[i] > 1) {
     75             for (j = sa[rk[i] - 1]; i + k <= n && j + k <= n && str[i + k] == str[j + k]; k++);
     76             hei[rk[i]] = k;
     77         } else
     78             hei[1] = 0;
     79     }
     80 }
     81 
     82 inline void solve() {
     83     build_sa();
     84     get_height();
     85 //    for (int i = 1; i <= n; i++)
     86 //        cerr << hei[i] << " ";
     87 //    cerr << endl;
     88     sort(qs + 1, qs + m + 1);
     89     long long cur = 0;
     90     for (int i = 1, nq = 1, delta; i <= n && nq <= m; i++) {
     91         delta = n - sa[i] + 1 - hei[i];
     92         if (cur + delta < qs[nq].k)
     93             cur += delta;
     94         else {
     95             qs[nq].s = sa[i], qs[nq].t = sa[i] + hei[i] + (qs[nq].k - cur);
     96             nq++, i--;
     97         }
     98     }
     99     for (int i = 1; i <= m; i++)
    100         while (qs[i].id != i)
    101             swap(qs[qs[i].id], qs[i]);
    102     for (int i = 1; i <= m; i++) {
    103         int len = qs[i].t - qs[i].s;
    104         memcpy(bs, str + qs[i].s , len);
    105         bs[len] = 0;
    106         puts(bs);    
    107     }
    108 }
    109 
    110 int main() {
    111     init();
    112     solve();
    113     return 0;
    114 }
  • 相关阅读:
    对于匿名对象,内部类这块的理解
    final等关键字和代码块
    构造方法
    接口与多态的总结
    关于折半法查找的一些总结以及ArrayList类的总结
    关于冒泡法的总结(主要是格式问题了)
    java读取properties文件的几种方式(转载)
    JAVA导出EXCEL表格(转载)
    map遍历的四种方法
    Java集合源码分析(四)HashMap
  • 原文地址:https://www.cnblogs.com/yyf0309/p/8643872.html
Copyright © 2011-2022 走看看