zoukankan      html  css  js  c++  java
  • 【BZOJ 3998】 3998: [TJOI2015]弦论 (SAM )

    3998: [TJOI2015]弦论

    Time Limit: 10 Sec  Memory Limit: 256 MB
    Submit: 2627  Solved: 881

    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

    Source

    【分析】

      建SAM,然后跑。

      right数组要按照拓扑序来求啊!!!!

      然后累计儿子的和的时候也要用拓扑序。

      具体拓扑序:

      

    for(int i=1;i<=tot;i++) v[t[i].step]++;
    for(int i=1;i<=tot;i++) v[i]+=v[i-1];
    for(int i=tot;i>=1;i--) q[v[t[i].step]--]=i;
    

      类似后缀数组那里的了。

      T=0,就right一开始都为1;T=1,就用right数组。

      空串算一个串,一开始k++。

      当然后缀数组也是可以的。

      1 #include<cstdio>
      2 #include<cstdlib>
      3 #include<cstring>
      4 #include<iostream>
      5 #include<algorithm>
      6 using namespace std;
      7 #define Maxn 500010
      8 
      9 struct node
     10 {
     11     int pre,last,son[30],step;
     12 }t[Maxn*2];
     13 int rt[Maxn*2],sm0[2*Maxn],sm1[2*Maxn];
     14 int v[2*Maxn],q[2*Maxn];
     15 
     16 struct sam
     17 {
     18     int last,tot;
     19     void extend(int k)
     20     {
     21         int np=++tot,p=last;
     22         t[np].step=t[last].step+1;
     23         rt[np]=1;
     24         while(p&&!t[p].son[k])
     25         {
     26             t[p].son[k]=np;
     27             p=t[p].pre;
     28         }
     29         if(!p) t[np].pre=1;
     30         else
     31         {
     32             int q=t[p].son[k];
     33             if(t[q].step==t[p].step+1) t[np].pre=q;
     34             else
     35             {
     36                 int nq=++tot;
     37                 memcpy(t[nq].son,t[q].son,sizeof(t[nq].son));
     38                 t[nq].step=t[p].step+1;
     39                 t[nq].pre=t[q].pre;
     40                 t[q].pre=t[np].pre=nq;
     41                 while(p&&t[p].son[k]==q)
     42                 {
     43                     t[p].son[k]=nq;
     44                     p=t[p].pre;
     45                 }
     46             }
     47         }
     48         last=np;
     49     }
     50     void init()
     51     {
     52         for(int i=1;i<=tot;i++) v[t[i].step]++;
     53         for(int i=1;i<=tot;i++) v[i]+=v[i-1];
     54         for(int i=tot;i>=1;i--) q[v[t[i].step]--]=i;
     55         
     56         // for(int i=1;i<=tot;i++) rt[i]=1;
     57         // for(int i=tot;i>=1;i--) rt[t[i].pre]+=rt[i];
     58         // rt[1]=1;
     59         for(int i=tot;i>=1;i--)
     60         {
     61             int nw=q[i];
     62             rt[t[nw].pre]+=rt[nw];
     63         }rt[1]=1;
     64         
     65         for(int i=tot;i>=1;i--)
     66         {
     67             int nw=q[i];
     68             sm0[nw]=1;sm1[nw]=rt[nw];
     69             for(int j=1;j<=26;j++) if(t[nw].son[j])
     70             {
     71                 sm0[nw]+=sm0[t[nw].son[j]];
     72                 sm1[nw]+=sm1[t[nw].son[j]];
     73             }
     74         }
     75     }
     76     void ffind(int opt,int k)
     77     {
     78         int sm,nw=1;
     79         k++;
     80         while(1)
     81         {
     82             sm=opt?rt[nw]:1;
     83             for(int i=1;i<=26;i++) if(t[nw].son[i])
     84             {
     85                 int ss=sm;
     86                 if(!opt) sm+=sm0[t[nw].son[i]];
     87                 else sm+=sm1[t[nw].son[i]];
     88                 if(sm>=k) {k-=ss;printf("%c",'a'+i-1);nw=t[nw].son[i];break;}
     89             }
     90             if(!opt&&k==1) break;
     91             if(opt&&k<=rt[nw]) break;
     92         }
     93         printf("
    ");
     94     }
     95 }sam;
     96 
     97 char s[Maxn];
     98 
     99 int main()
    100 {
    101     scanf("%s",s);
    102     int l=strlen(s);
    103     sam.last=sam.tot=1;
    104     for(int i=0;i<l;i++) sam.extend(s[i]-'a'+1);
    105     sam.init();
    106     int opt,k;
    107     scanf("%d%d",&opt,&k);
    108     if(!opt&&k+1>sm0[1]) printf("-1
    ");
    109     else if(opt&&k+rt[1]>sm1[1]) printf("-1
    ");
    110     else sam.ffind(opt,k);
    111     return 0;
    112 }
    View Code

    2017-04-17 13:59:36

      

  • 相关阅读:
    Ubuntu配置sublime text 3的c编译环境
    ORA-01078错误举例:SID的大写和小写错误
    linux下多进程的文件拷贝与进程相关的一些基础知识
    ASM(四) 利用Method 组件动态注入方法逻辑
    基于Redis的三种分布式爬虫策略
    Go语言并发编程总结
    POJ2406 Power Strings 【KMP】
    nyoj 会场安排问题
    Server Tomcat v7.0 Server at localhost was unable to start within 45 seconds. If the server requires more time, try increasing the timeout in the server editor.
    Java的String、StringBuffer和StringBuilder的区别
  • 原文地址:https://www.cnblogs.com/Konjakmoyu/p/6722630.html
Copyright © 2011-2022 走看看