zoukankan      html  css  js  c++  java
  • BZOJ 3998 TJOI2015 弦论 后缀自动机+DAG上的dp

    题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=3998

    题意概述:对于一个给定长度为N的字符串,求它的第K小子串是什么,T为0则表示不同位置的相同子串算作一个。T=1则表示不同位置的相同子串算作多个。N<=500000,K<=10^9.

    应该是有三种做法的(当然后缀树我还没有看),于是就把这个东西当成后缀自动机的板子了(因为它很裸啊!!!)。

    可以注意到当T=0的时候每走动一步的贡献是1,而T=1的时候每走动一步之后的贡献都是走到的这个状态的right集合大小。同时从同一个状态走出去得到的字符串又有很多种,不难想到可以搞个dp表示从这个点出发(包括这个点自己)可以找到的不同子串数(根据T而定)。

    有个技巧是根据MAX把所有的状态排序之后就可以欢快地topo图上转移dp啦!(SAM的转移图是一张DAG)

    所以还是好好理解一下SAM上的状态和转移吧,,,。。。。

     1 #include<iostream>
     2 #include<cstdio>
     3 #include<cstring>
     4 #include<cstdlib>
     5 #include<algorithm>
     6 #include<cmath>
     7 #include<queue>
     8 #include<set>
     9 #include<map>
    10 #include<vector>
    11 #include<cctype>
    12 using namespace std;
    13 const int MAXN=500005;
    14 
    15 int T,K,n; char S[MAXN];
    16 
    17 struct SAM{
    18     static const int maxn=500005;
    19     static const int sigma_sz=26;
    20     int pa[maxn<<1],to[maxn<<1][sigma_sz],mx[maxn<<1],val[maxn<<1]; long long cnt[maxn<<1];
    21     int sz,last,c[maxn],a[maxn<<1];
    22     SAM(){ last=sz=1; memset(to[1],0,sizeof(to[1])); }
    23     int newnode(){
    24         memset(to[++sz],0,sizeof(to[sz]));
    25         pa[sz]=mx[sz]=val[sz]=cnt[sz]=0;
    26         return sz;
    27     }
    28     void extend(int w){
    29         int p=last,np=newnode(); last=np;
    30         pa[np]=mx[np]=cnt[np]=0;
    31         mx[np]=mx[p]+1,val[np]=1;
    32         while(p&&!to[p][w]) to[p][w]=np,p=pa[p];
    33         if(!p) pa[np]=1;
    34         else{
    35             int q=to[p][w];
    36             if(mx[p]+1==mx[q]) pa[np]=q;
    37             else{
    38                 int nq=newnode(); mx[nq]=mx[p]+1;
    39                 memcpy(to[nq],to[q],sizeof(to[nq]));
    40                 pa[nq]=pa[q];
    41                 pa[np]=pa[q]=nq;
    42                 while(p&&to[p][w]==q) to[p][w]=nq,p=pa[p];
    43             }
    44         }
    45     }
    46     void ready(){
    47         for(int i=1;i<=sz;i++) c[mx[i]]++;
    48         for(int i=1;i<=n;i++) c[i]+=c[i-1];
    49         for(int i=sz;i>0;i--) a[c[mx[i]]--]=i;
    50         for(int i=sz;i>0;i--){
    51             if(T) val[pa[a[i]]]+=val[a[i]];
    52             else val[a[i]]=1;
    53         }
    54         val[1]=0;
    55         for(int i=sz;i>0;i--){
    56             cnt[a[i]]=val[a[i]];
    57             for(int j=0;j<26;j++) cnt[a[i]]+=cnt[to[a[i]][j]];
    58         }
    59     }
    60     void dfs(int i){
    61         if(val[i]>=K) return;
    62         K-=val[i];
    63         for(int j=0;j<26;j++) if(to[i][j]){
    64             if(cnt[to[i][j]]>=K){
    65                 putchar(j+'a'); dfs(to[i][j]);
    66                 return;
    67             }
    68             K-=cnt[to[i][j]];
    69         }
    70     }
    71 }sam;
    72 
    73 void data_in()
    74 {
    75     gets(S);
    76     scanf("%d%d",&T,&K);
    77 }
    78 void work()
    79 {
    80     n=strlen(S);
    81     for(int i=0;i<n;i++) sam.extend(S[i]-'a');
    82     sam.ready();
    83     if(sam.cnt[1]<K) printf("%d
    ",-1);
    84     else sam.dfs(1);
    85 }
    86 int main()
    87 {
    88     data_in();
    89     work();
    90     return 0;
    91 }
  • 相关阅读:
    Java虚拟机的内存模型
    JAVA 对文件的操作
    JAVA 读取 YAML 文件
    Nginx 502 问题解决 及 安装
    Python pdb 调试 命令
    pycharm设置鼠标控制字体大小
    ISO9126 软件质量模型
    人生苦短我学Java9面向对象三大特性之多态 广深
    Golang微服务入门到精通之路3类的封装/继承/多态/接口类型 广深
    人生苦短我学Java10final关键字/代码块/抽象类 广深
  • 原文地址:https://www.cnblogs.com/KKKorange/p/8527642.html
Copyright © 2011-2022 走看看