• bzoj3998 && [TJOI2015]弦论


    传送门:http://www.lydsy.com/JudgeOnline/problem.php?id=3998

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

    题解:后缀自动机

       我们可以这样想:1.从一个节点u开始到v1,v2两点,u,v1,v2在一条路径上,len值大的K值就更大,例如:aab<aabb;

               2.从一个节点u开始到v1分开到v2,v3,那么u-->v1-->v2 && u-->v1---->v3的k值则由v1---v2和v1----v3决定。

               所以我们就可以很容易进行比较大小,利用一下后缀自动机的树状结构,细节见代码。

    代码:

     1 #include<algorithm>
     2 #include<iostream>
     3 #include<cstring>
     4 #include<cstdio>
     5 #include<cmath>
     6 #define maxn 1000005
     7 using namespace std;
     8 char s[maxn];
     9 int T,K;
    10 int root,tot,last,m;
    11 struct data{
    12     int sum[maxn],ssum[maxn],fa[maxn],son[maxn][26],val[maxn],ri[maxn],tmp[maxn],kkd; 
    13     int prepare(){last=root=tot=1;}
    14     int newnode(int x) {val[++tot]=x; return tot;}
    15     void extend(int x)
    16     {
    17         int p=last,np=newnode(val[p]+1);last=np; ri[np]=1;
    18         for (; p && !son[p][x]; p=fa[p]) son[p][x]=np;
    19         if (!p) fa[np]=root;
    20         else
    21         {
    22             int q=son[p][x];
    23             if (val[q]==val[p]+1) fa[np]=q;
    24             else
    25             {
    26                 int nq=newnode(val[p]+1);
    27                 memcpy(son[nq],son[q],sizeof(son[q]));
    28                 fa[nq]=fa[q];
    29                 fa[q]=fa[np]=nq;
    30                 for (; p && son[p][x]==q; p=fa[p]) son[p][x]=nq; 
    31             }
    32         }
    33         
    34     }
    35     void pre()
    36     {
    37         for (int i=1; i<=tot; i++) sum[val[i]]++;
    38         for (int i=1; i<=tot; i++) sum[i]+=sum[i-1];
    39         for (int i=tot; i; i--) tmp[sum[val[i]]--]=i;
    40         for (int i=tot; i; i--)
    41         {
    42             int v=tmp[i];
    43             if (T==1) ri[fa[v]]+=ri[v];
    44             else ri[v]=1;
    45         }
    46         ri[1]=0;
    47         for (int i=tot; i; i--)
    48         {
    49             int v=tmp[i]; ssum[v]=ri[v];
    50             for (int p=0; p<=25; p++)
    51                 ssum[v]+=ssum[son[v][p]];
    52         }
    53         
    54     }
    55     void build()
    56     {
    57         prepare();
    58         for (int i=1; i<=m; i++) extend(s[i]-'a');
    59     }
    60     void dfs(int x,int k)
    61     {
    62         if (k<=ri[x]) return;
    63         k-=ri[x];
    64         for (int i=0; i<=25; i++)
    65         {
    66             if (ssum[son[x][i]]>=k) 
    67             {
    68                 putchar(i+'a');
    69                 dfs(son[x][i],k);
    70                 return ;
    71             }
    72             k-=ssum[son[x][i]];
    73         }
    74      }
    75 }SAM;
    76 int main()
    77 {
    78     scanf("%s",s+1); m=strlen(s+1);
    79     scanf("%d%d",&T,&K);
    80     SAM.build();
    81     SAM.pre();
    82     if (K>SAM.ssum[root]) printf("-1");
    83     else SAM.dfs(root,K);
    84     printf("
    ");
    85     return 0;
    86 }
    View Code

    开始时间:20:40

    结束时间:21:20

  • 相关阅读:
    DNS智能双向解析怎么做?
    高防服务器如何选择性价比最高?
    20192416 实验四《Python程序设计》综合实践报告
    20192416实验三 《Python程序设计》实验报告
    20192416 《Python程序设计》实验二报告
    20192416 《Python程序设计》实验一报告
    2019-2020-1学期 20192416《网络空间安全专业导论》第十二周学习总结
    2019-2020-1学期 20192416《网络空间安全专业导论》第十一周学习总结
    2019-2020-1学期 20192416《网络空间安全专业导论》第十周学习总结
    2019-2020-1学期 20192416《网络空间安全专业导论》第九周学习总结
  • 原文地址:https://www.cnblogs.com/HQHQ/p/5551762.html
Copyright © 2020-2023  润新知