• bzoj 3998


    后缀自动机上dfs,查询第k大子串

    注意代码复杂度,可以不需要加边,写简洁的代码

      1 #include<iostream>
      2 #include<cstdio>
      3 #include<cstring>
      4 #include<algorithm>
      5 using namespace std;
      6 #define maxn 1000020
      7 
      8 struct node{
      9     int val,pnt,size,degree;
     10     int next[27];
     11 }sam[maxn];
     12 struct node2{
     13     int to,next;
     14 }e[maxn * 2];
     15 int tot,n,k,cnt,t,last,root,head[maxn];
     16 long long sum[maxn];
     17 int pnt[maxn];
     18 char data[500020];
     19 int q[maxn],hh,tt,size[maxn];
     20 
     21 inline void add(int x){
     22     int np = ++tot;
     23     int p = last;
     24     sam[np].val = sam[p].val + 1;
     25     while ( p && !sam[p].next[x] ){
     26         sam[p].next[x] = np , p = sam[p].pnt;
     27         sam[np].degree++;
     28     }
     29     int q = sam[p].next[x];
     30     if ( !q ){
     31         sam[p].next[x] = np;
     32         sam[np].pnt = p;
     33         sam[np].degree++;
     34     }
     35     else if ( q && sam[q].val == sam[p].val + 1 ){
     36         sam[np].pnt = q;
     37     }    
     38     else{
     39         int nq = ++tot;
     40         sam[nq].pnt = sam[q].pnt;
     41         sam[np].pnt = sam[q].pnt = nq;
     42         sam[nq].val = sam[p].val + 1;
     43         //memcpy(sam[nq].next,sam[q].next,sizeof(sam[q].next));
     44         for (int i = 0 ; i < 26 ; i++){
     45             if ( sam[q].next[i] ){
     46                 sam[nq].next[i] = sam[q].next[i];
     47                 sam[sam[q].next[i]].degree++;
     48             }
     49         }
     50         while ( p && sam[p].next[x] == q ){
     51             sam[p].next[x] = nq , p = sam[p].pnt;
     52             sam[nq].degree++;
     53             sam[q].degree--;
     54         }
     55         if ( sam[p].next[x] == q ){
     56             sam[p].next[x] = nq;
     57             sam[nq].degree++ , sam[q].degree--;
     58         }
     59     }
     60     last = np;
     61 }
     62 inline void addedge(int x,int y){
     63     e[++cnt].to = y;
     64     e[cnt].next = head[x];
     65     head[x] = cnt;
     66 }
     67 inline void bfs(int now){
     68     tt = hh = 0;
     69     q[tt++] = now;
     70     while ( hh < tt ){
     71         now = q[hh++];
     72         for (int i = head[now] ; i ; i = e[i].next){
     73             if ( pnt[now] == e[i].to ) continue;
     74             q[tt++] = e[i].to;
     75         }
     76     }
     77     for (int i = tt - 1 ; i >= 0; i--){
     78         size[q[i]] += 1;
     79         size[pnt[q[i]]]    += size[q[i]];
     80     }
     81 }
     82 void topo(){
     83     tt = hh = 0;
     84     for (int i = 0 ; i <= tot ; i++){
     85         if ( !sam[i].degree ) q[tt++] = i;
     86     }
     87     while ( hh < tt ){
     88         int now = q[hh++];
     89         for (int i = 0 ; i < 26 ; i++){
     90             if ( sam[now].next[i] ){
     91                 int to = sam[now].next[i];
     92                 sam[to].degree--;
     93                 if ( sam[to].degree == 0 ) q[tt++] = to;
     94             }
     95         }
     96     }
     97 }
     98 inline void getsum1(){
     99     for (int i = tt - 1 ; i >= 0 ; i--){
    100         sum[q[i]] = 1;
    101         for (int j = 0 ; j < 26 ; j++){
    102             if ( sam[q[i]].next[j] ){
    103                 sum[q[i]] += sum[sam[q[i]].next[j]];
    104             }
    105         }
    106     }
    107 }
    108 inline void getsum2(){
    109     for (int i = tt - 1 ; i >= 0 ; i--){
    110         sum[q[i]] = size[q[i]];
    111         for (int j = 0 ; j < 26 ; j++){
    112             if ( sam[q[i]].next[j] ){
    113                 sum[q[i]] += sum[sam[q[i]].next[j]];
    114             }
    115         }
    116     }
    117 }
    118 inline void dfs1(int now,long long k){
    119     k--;
    120     if ( k <= 0 ) return;
    121     for (int i = 0 ; i < 26 ; i++){
    122         if ( sam[now].next[i] ){
    123             if ( sum[sam[now].next[i]] >= k ){
    124                 printf("%c",char(i + 'a'));
    125                    dfs1(sam[now].next[i],k);
    126                 break;
    127             }
    128             else k -= sum[sam[now].next[i]];
    129         }
    130     }
    131 }
    132 inline void dfs2(int now,long long k){
    133     k -= (long long) size[now];
    134     if ( k <= 0 ) return;
    135     for (int i = 0 ; i < 26 ; i++){
    136         if ( sam[now].next[i] ){
    137             if ( sum[sam[now].next[i]] >= k ){
    138                 printf("%c",char(i + 'a'));
    139                    dfs2(sam[now].next[i],k);
    140                 break;
    141             }
    142             else k -= sum[sam[now].next[i]];
    143         }
    144     }
    145 }
    146 int main(){
    147 //    freopen("input.txt","r",stdin);
    148     int __size__ = 50 << 20; // 25MB
    149     char *__p__ = (char*)malloc(__size__) + __size__;
    150     __asm__("movl %0, %%esp
    " :: "r"(__p__));    
    151     scanf("%s",data + 1);
    152     n = strlen(data + 1);
    153     scanf("%d %d",&t,&k);
    154     for (int i = 1 ; i <= n ; i++){
    155         add(int(data[i] - 'a'));
    156     }
    157     for (int i = 1 ; i <= tot ; i++){
    158         pnt[i] = sam[i].pnt;
    159         addedge(pnt[i],i);
    160         addedge(i,pnt[i]);
    161     }
    162     bfs(root);
    163     topo();
    164 //    for (int i = 0 ; i <= tot ; i++) cout<<size[i]<<" ";
    165 //    cout<<endl;
    166     if ( t == 0 ){
    167         getsum1();
    168         long long bl = 0;
    169         for (int i = 1 ; i <= tot ; i++){
    170             bl += sam[i].val - sam[sam[i].pnt].val;
    171         }
    172         if ( bl >= k ) dfs1(root,(long long) k + 1);
    173         else printf("-1
    ");
    174     }
    175     else{
    176         getsum2();
    177         long long bl = (long long) n * ((long long) n - 1) / 2;
    178         if ( bl >= k ) dfs2(root,(long long) k + size[root]);
    179         else printf("-1
    ");
    180     }
    181     return 0;
    182 }
  • 相关阅读:
    SQL数据库一直显示正在还原
    jQuery获取display为none的隐藏元素的宽度和高度的解决方案
    火狐打开新标签页面不出现九宫格的设置
    【转】在C#中?,?:和??
    【转】JS字符(字母)与ASCII码转换方法
    如何为 .NET Core 安装本地化的 IntelliSense 文件
    compass typography 排版 常用排版方法[Sass和compass学习笔记]
    单元测试 逃不开的Done 与约定
    SASS+COMPASS 自适应 学习笔记
    compass tables 表格 表格常见样式[Sass和compass学习笔记]
  • 原文地址:https://www.cnblogs.com/zqq123/p/5119739.html
Copyright © 2020-2023  润新知