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\n" :: "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\n");
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\n");
180     }
181     return 0;
182 }

 

posted @ 2016-01-10 22:33  zhangqingqi  阅读(232)  评论(0编辑  收藏  举报