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 }