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 }
  • 相关阅读:
    AJAX和DHTML
    解析xml的4种方法详解
    javascript -window与document 待整理
    JavaScript中的shift()、unshift()和pop()函数
    JS中如何定义全局变量
    j中的substr(start,length)和substring(start,stop)
    JS中的唯一容器:数组
    typeof()和instanceof的用法区别
    JS和DOM的关系
    jQuery对象与DOM对象之间的转换方法
  • 原文地址:https://www.cnblogs.com/weeping/p/7522495.html
Copyright © 2011-2022 走看看