zoukankan      html  css  js  c++  java
  • bzoj3998 [TJOI2015]弦论

    地址:http://www.lydsy.com/JudgeOnline/problem.php?id=3998

    题面:

    3998: [TJOI2015]弦论

    Time Limit: 10 Sec  Memory Limit: 256 MB
    Submit: 3127  Solved: 1079

    Description

    对于一个给定长度为N的字符串,求它的第K小子串是什么。

    Input

     第一行是一个仅由小写英文字母构成的字符串S

    第二行为两个整数T和K,T为0则表示不同位置的相同子串算作一个。T=1则表示不同位置的相同子串算作多个。K的意义如题所述。

    Output

    输出仅一行,为一个数字串,为第K小的子串。如果子串数目不足K个,则输出-1

    Sample Input

    aabc
    0 3

    Sample Output

    aab

    HINT

     N<=5*10^5


    T<2

    K<=10^9
     
    思路:  
      对于t=1的情况,把每个状态的cnt记为1.
      t=0时,把cnt记为endpos集合的大小。
      然后dp即可。
      1 /**************************************************************
      2     Problem: 3998
      3     User: weeping
      4     Language: C++
      5     Result: Accepted
      6     Time:6736 ms
      7     Memory:122876 kb
      8 ****************************************************************/
      9  
     10 #include <bits/stdc++.h>
     11  
     12 using namespace std;
     13  
     14  
     15  
     16 struct SAM
     17 {
     18     static const int MAXN = 500002<<1;//大小为字符串长度两倍
     19     static const int LetterSize = 26;
     20  
     21     int tot, last, ch[MAXN][LetterSize], fa[MAXN], len[MAXN];
     22     int sum[MAXN], tp[MAXN], cnt[MAXN]; //sum,tp用于拓扑排序,tp为排序后的数组
     23  
     24     void init( void)
     25     {
     26         last = tot = 1;
     27         len[1] = 0;
     28         memset(ch,0,sizeof ch);
     29         memset(fa,0,sizeof fa);
     30         memset(cnt,0,sizeof cnt);
     31     }
     32  
     33     void add( int x)
     34     {
     35         int p = last, np = last = ++tot;
     36         len[np] = len[p] + 1, cnt[last] = 1;
     37         while( p && !ch[p][x]) ch[p][x] = np, p = fa[p];
     38         if( p == 0)
     39             fa[np] = 1;
     40         else
     41         {
     42             int q = ch[p][x];
     43             if( len[q] == len[p] + 1)
     44                 fa[np] = q;
     45             else
     46             {
     47                 int nq = ++tot;
     48                 memcpy( ch[nq], ch[q], sizeof ch[q]);
     49                 len[nq] = len[p] + 1, fa[nq] = fa[q], fa[q] = fa[np] = nq;
     50                 while( p && ch[p][x] == q)  ch[p][x] = nq, p = fa[p];
     51             }
     52         }
     53     }
     54  
     55     void toposort( void)
     56     {
     57         for(int i = 1; i <= len[last]; i++)   sum[i] = 0;
     58         for(int i = 1; i <= tot; i++)   sum[len[i]]++;
     59         for(int i = 1; i <= len[last]; i++)   sum[i] += sum[i-1];
     60         for(int i = 1; i <= tot; i++)   tp[sum[len[i]]--] = i;
     61         for(int i = tot; i; i--)   cnt[fa[tp[i]]] += cnt[tp[i]];
     62     }
     63  
     64     void solve( int t, int k)
     65     {
     66         for(int i = 1; i <= len[last]; i++)   sum[i] = 0;
     67         for(int i = 1; i <= tot; i++)   sum[len[i]]++;
     68         for(int i = 1; i <= len[last]; i++)   sum[i] += sum[i-1];
     69         for(int i = 1; i <= tot; i++)   tp[sum[len[i]]--] = i;
     70         for(int i = tot; i; i--)
     71         if(t)   cnt[fa[tp[i]]] += cnt[tp[i]];
     72         else cnt[i] = 1;
     73         cnt[1]=0;
     74         for(int i = 1; i <= tot; i++)   sum[i] = cnt[i];
     75         for(int i = tot; i; i--)
     76         for(int j = 0; j < 26; j++)
     77             sum[tp[i]] += sum[ch[tp[i]][j]];
     78         if(sum[1]<k) {printf("-1
    ");return;}
     79         int p=1;
     80         while(k>0)
     81         {
     82             for(int j = 0; j < 26; j++)
     83             if(sum[ch[p][j]]>=k)
     84             {
     85                 printf("%c",'a'+j),p=ch[p][j],k-=cnt[p];
     86                 break;
     87             }
     88             else
     89                 k-=sum[ch[p][j]];
     90         }
     91     }
     92 } sam;
     93  
     94 char ss[500004];
     95  
     96 int main(void)
     97 {
     98     int t,k;
     99     //freopen("in.acm","r",stdin);
    100     sam.init();
    101     scanf("%s%d%d",ss,&t,&k);
    102     for(int i=0,len=strlen(ss);i<len;i++)  sam.add(ss[i]-'a');
    103     sam.solve(t,k);
    104     return 0;
    105 }
  • 相关阅读:
    Serialize and Deserialize Binary Tree
    sliding window substring problem汇总贴
    10. Regular Expression Matching
    《深入理解计算机系统》(CSAPP)读书笔记 —— 第七章 链接
    程序员如何写一份合格的简历?(附简历模版)
    9个提高代码运行效率的小技巧你知道几个?
    《深入理解计算机系统》(CSAPP)读书笔记 —— 第六章 存储器层次结构
    24张图7000字详解计算机中的高速缓存
    《深入理解计算机系统》(CSAPP)实验四 —— Attack Lab
    《深入理解计算机系统》(CSAPP)读书笔记 —— 第五章 优化程序性能
  • 原文地址:https://www.cnblogs.com/weeping/p/7522495.html
Copyright © 2011-2022 走看看