zoukankan      html  css  js  c++  java
  • 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 }
  • 相关阅读:
    jquery 序列化form表单
    nginx for windows 安装
    nodejs idea 创建项目 (一)
    spring 配置 shiro rememberMe
    idea 2018 解决 双击shift 弹出 search everywhere 搜索框的方法
    redis 在windows 集群
    spring IOC控制反转和DI依赖注入
    redis 的安装
    shiro 通过jdbc连接数据库
    handlebars的用法
  • 原文地址:https://www.cnblogs.com/zqq123/p/5119739.html
Copyright © 2011-2022 走看看