zoukankan      html  css  js  c++  java
  • SPOJ SUBLEX

    SUBLEX - Lexicographical Substring Search

    链接

    题意

      求第k小的子串。相同的算一个。

    分析

      建立后缀自动机,在后缀自动机上从一个点经过trans,到另一个点,trans会对应一个子串。而且会对应所有的子串。

      每个节点能经过trans到达的点,即它可以形成的子串。所有按照拓扑序更新每个节点能形成多少个子串,如果经过当前点形成的串小于k,那么说明第k小的串不经过高这个点,k-=siz,继续找,如果小于这个的siz,那么就经过这个点,输出。有点像二叉搜索树的查询。

    代码

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 typedef long long LL;
     4 
     5 inline int read() {
     6     int x=0,f=1;char ch=getchar();for(;!isdigit(ch);ch=getchar())if(ch=='-')f=-1;
     7     for (;isdigit(ch);ch=getchar())x=x*10+ch-'0';return x*f;
     8 }
     9 
    10 const int N = 200100;
    11 
    12 struct SuffixAutomaton{
    13     int Last, Index, fa[N], len[N], trans[N][26];
    14     int v[N],sa[N],siz[N];
    15     char s[N];
    16     void extend(int c) {
    17         int P = Last, NP = ++Index;
    18         len[NP] = len[P] + 1;
    19         for (; P&&!trans[P][c]; P=fa[P]) trans[P][c] = NP;
    20         if (!P) fa[NP] = 1;
    21         else {
    22             int Q = trans[P][c];
    23             if (len[P] + 1 == len[Q]) fa[NP] = Q;
    24             else {
    25                 int NQ = ++Index;
    26                 fa[NQ] = fa[Q];
    27                 len[NQ] = len[P] + 1;
    28                 memcpy(trans[NQ], trans[Q], sizeof trans[Q]);
    29                 fa[Q] = NQ;
    30                 fa[NP] = NQ;
    31                 for (; P&&trans[P][c]==Q; P=fa[P]) trans[P][c] = NQ;
    32             }
    33         }
    34         Last = NP;
    35     }
    36     void build() {
    37         Last = Index = 1; //---老是忘记这里。。。 
    38         scanf("%s",s+1);
    39         int n = strlen(s+1);
    40         for (int i=1; i<=n; ++i) extend(s[i] - 'a');
    41         for (int i=1; i<=Index; ++i) v[len[i]] ++;
    42         for (int i=1; i<=n; ++i) v[i] += v[i-1];
    43         for (int i=1; i<=Index; ++i) sa[ v[len[i]]-- ] = i;
    44     }
    45     
    46     void init() {
    47         for (int i=Index; i>=1; --i) {
    48             int t = sa[i];
    49             siz[t] ++;
    50             for (int j=0; j<26; ++j) {
    51                 if (trans[t][j]) siz[t] += siz[trans[t][j]];
    52             }
    53         }
    54     }
    55     void query(int k) {
    56         int p = 1;
    57         while (k) 
    58             for (int i=0; i<26; ++i) 
    59                 if (trans[p][i]) 
    60                     if (k > siz[trans[p][i]]) k -= siz[trans[p][i]];
    61                     else {
    62                         printf("%c",i+'a');
    63                         p = trans[p][i];
    64                         k--;
    65                         break;
    66                     }
    67     }
    68     void solve() {
    69         build();
    70         init();
    71         int m = read(),k;
    72         while (m--) {
    73             k = read();
    74             query(k);
    75             puts("");
    76         }
    77     }
    78 }sam;
    79 
    80 int main() {
    81     sam.solve();
    82     return 0;
    83 }
  • 相关阅读:
    正则表达式
    webfrom 母版页
    repeater的command事件用法
    JVM进程cpu飙高分析
    @Transactional导致无法动态数据源切换
    mysql分页查询优化(索引延迟关联)
    MAC下安装Homebrew 和 @权限的问题
    RabbitMQ安装以及集群部署
    RabbitMQ 延时消息队列
    java 实现生产者-消费者模式
  • 原文地址:https://www.cnblogs.com/mjtcn/p/9337136.html
Copyright © 2011-2022 走看看