• 解题:TJOI 2015 弦论


    题面

    好像是个经典问题,然而我没做过

    建SAM,然后经过每个节点的子串数目就可以求了,多个相同子串算一个的话就把所有siz都搞成$1$,否则就是$right$集合的大小,然后就是常见的递推

    求第$k$小是从根节点出发按字典序沿着trans往下走,每次输出对应的字符然后扣掉对应的数量

     1 #include<cstdio>
     2 #include<cstring>
     3 #include<algorithm>
     4 using namespace std;
     5 const int N=500005,M=1000005;
     6 int fth[M],trs[M][26],len[M],siz[M];
     7 int rnk[M],bkt[M]; long long sum[M];
     8 int typ,kth,lth,lst,tot;
     9 char str[N];
    10 void Insert(int ch)
    11 {
    12     int nde=lst,newn=++tot; lst=newn;
    13     siz[newn]=1,len[newn]=len[nde]+1;
    14     while(nde&&!trs[nde][ch])
    15         trs[nde][ch]=newn,nde=fth[nde];
    16     if(!nde)
    17         fth[newn]=1;
    18     else
    19     {
    20         int tran=trs[nde][ch];
    21         if(len[tran]==len[nde]+1)
    22             fth[newn]=tran;
    23         else
    24         {
    25             int rnde=++tot; len[rnde]=len[nde]+1;
    26             for(int i=0;i<=25;i++) trs[rnde][i]=trs[tran][i];
    27             fth[rnde]=fth[tran],fth[tran]=fth[newn]=rnde;
    28             while(nde&&trs[nde][ch]==tran)
    29                 trs[nde][ch]=rnde,nde=fth[nde];
    30         }
    31     }
    32 }
    33 int main()
    34 {
    35     register int i,j,k;
    36     scanf("%s%d%d",str+1,&typ,&kth);
    37     lth=strlen(str+1),lst=tot=1;
    38     for(i=1;i<=lth;i++) Insert(str[i]-'a');
    39     for(i=1;i<=tot;i++) bkt[len[i]]++;
    40     for(i=1;i<=lth;i++) bkt[i]+=bkt[i-1];
    41     for(i=1;i<=tot;i++) rnk[bkt[len[i]]--]=i;
    42     for(i=tot;i;i--)
    43         j=rnk[i],typ?siz[fth[j]]+=siz[j]:siz[j]=1;
    44     siz[1]=0;
    45     for(i=tot;i;i--)
    46     {
    47         j=rnk[i],sum[j]=siz[j];
    48         for(k=0;k<=25;k++)
    49             if(trs[j][k]) sum[j]+=sum[trs[j][k]];
    50     } 
    51     if(kth>sum[1]) printf("-1");
    52     else
    53     {
    54         int nde=1;
    55         while(kth-siz[nde]>0)
    56         {
    57             kth-=siz[nde];
    58             for(i=0;i<=25&&kth>sum[trs[nde][i]];i++)    
    59                 kth-=sum[trs[nde][i]];
    60             nde=trs[nde][i],printf("%c",i+'a');
    61         }
    62     }
    63     return 0;
    64 }
    View Code
  • 相关阅读:
    html 标签分类
    第三课 物理地址和几条汇编指令
    第二课 寄存器
    第一课 基础知识
    利用队列进行二叉树的层次遍历
    二叉树前序创建三种遍历 代码亲测
    记录
    My97 DatePicker 全局显示、隐藏
    Available Memory Is Low
    connect by prior...start with...
  • 原文地址:https://www.cnblogs.com/ydnhaha/p/10148330.html
Copyright © 2020-2023  润新知