生活随笔
收集整理的這篇文章主要介紹了
HDU - 6704 K-th occurrence (后缀数组+主席树)
小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.
題目鏈接
題意
QQQ次詢問,每次詢問求SSS的子串出現(xiàn)KKK次的位置
思路
剛開始想的是AC自動機,但是建自動機會超時,后來學長想到后綴數(shù)組+主席樹的做法Orz...Orz...Orz...
出現(xiàn)KKK次的字符串,在后綴數(shù)組中連續(xù)出現(xiàn),求出詢問對應(yīng)后綴前后滿足區(qū)間內(nèi)的height>=lenheight >= lenheight>=len的最長的區(qū)間,此時區(qū)間[L,R][L, R][L,R]對應(yīng)的位置都包含子串,主席樹找[L,R][L, R][L,R]中第K小的位置即可
#include <bits/stdc++.h>
#define endl '\n'
const int maxn
= 1e5 + 5;
const int inf
= 0x3f3f3f3f;
const int mod
= 1e9 + 7;
using namespace std
;
char s
[maxn
];
struct Tree
{int tot
, rt
[maxn
], lson
[maxn
*20], rson
[maxn
*20], cnt
[maxn
*20];int build
(int l
, int r
) {int o
= ++tot
;int mid
= (l
+ r
) >> 1;cnt
[o
] = 0;if (l
!= r
) {lson
[o
] = build(l
, mid
);rson
[o
] = build(mid
+1, r
);}return o
;}int update(int prev
, int l
, int r
, int v
) {int o
= ++tot
;int mid
= (l
+ r
) >> 1;lson
[o
] = lson
[prev
];rson
[o
] = rson
[prev
];cnt
[o
] = cnt
[prev
] + 1;if (l
!= r
) {if (v
<= mid
) lson
[o
] = update(lson
[o
], l
, mid
, v
);else rson
[o
] = update(rson
[o
], mid
+1, r
, v
);}return o
;}int query(int u
, int v
, int l
, int r
, int k
) {if (l
== r
) return l
;int mid
= (l
+ r
) >> 1;int num
= cnt
[lson
[v
]] - cnt
[lson
[u
]];if (num
>= k
) return query(lson
[u
], lson
[v
], l
, mid
, k
);else return query(rson
[u
], rson
[v
], mid
+1, r
, k
-num
);}
};
struct SuffixArray
{ int cntA
[maxn
], cntB
[maxn
], A
[maxn
], B
[maxn
];int Sa
[maxn
], tsa
[maxn
], height
[maxn
], Rank
[maxn
]; int n
, dp
[maxn
][18];Tree T
;void build() {T
.tot
= 0;T
.rt
[0] = T
.build(1, n
);for (int i
= 1; i
<= n
; ++i
) T
.rt
[i
] = T
.update(T
.rt
[i
-1], 1, n
, Sa
[i
]);}void init(char *buf
, int len
) { n
= len
;for (int i
= 0; i
< 128; ++i
) cntA
[i
] = 0;for (int i
= 1; i
<= n
; ++i
) cntA
[(int)buf
[i
]]++;for (int i
= 1; i
< 128; ++i
) cntA
[i
] += cntA
[i
-1];for (int i
= n
; i
>= 1; --i
) Sa
[ cntA
[(int)buf
[i
]]-- ] = i
;Rank
[ Sa
[1] ] = 1;for (int i
= 2; i
<= n
; ++i
) {Rank
[Sa
[i
]] = Rank
[Sa
[i
-1]];if (buf
[Sa
[i
]] != buf
[Sa
[i
-1]]) Rank
[Sa
[i
]]++;}for (int l
= 1; Rank
[Sa
[n
]] < n
; l
<<= 1) {for (int i
= 0; i
<= n
; ++i
) cntA
[i
] = 0;for (int i
= 0; i
<= n
; ++i
) cntB
[i
] = 0;for (int i
= 1; i
<= n
; ++i
) {cntA
[ A
[i
] = Rank
[i
] ]++;cntB
[ B
[i
] = (i
+ l
<= n
) ? Rank
[i
+l
] : 0]++;}for (int i
= 1; i
<= n
; ++i
) cntB
[i
] += cntB
[i
-1];for (int i
= n
; i
>= 1; --i
) tsa
[ cntB
[B
[i
]]-- ] = i
;for (int i
= 1; i
<= n
; ++i
) cntA
[i
] += cntA
[i
-1];for (int i
= n
; i
>= 1; --i
) Sa
[ cntA
[A
[tsa
[i
]]]-- ] = tsa
[i
];Rank
[ Sa
[1] ] = 1;for (int i
= 2; i
<= n
; ++i
) {Rank
[Sa
[i
]] = Rank
[Sa
[i
-1]];if (A
[Sa
[i
]] != A
[Sa
[i
-1]] || B
[Sa
[i
]] != B
[Sa
[i
-1]]) Rank
[Sa
[i
]]++;}}for (int i
= 1, j
= 0; i
<= n
; ++i
) {if (j
) --j
;int tmp
= Sa
[Rank
[i
] - 1];while (i
+ j
<= n
&& tmp
+ j
<= n
&& buf
[i
+j
] == buf
[tmp
+j
]) ++j
;height
[Rank
[i
]] = j
;}}void st() {for (int i
= 1; i
<= n
; ++i
) {dp
[i
][0] = height
[i
];}for (int j
= 1; j
<= log2(n
); ++j
) {for (int i
= 1; i
+ (1 << j
) - 1 <= n
; ++i
) {dp
[i
][j
] = min(dp
[i
][j
- 1], dp
[i
+ (1 << (j
- 1))][j
- 1]);}}}int rmq(int l
, int r
) {if (l
== r
) return inf
;l
++;int len
= r
- l
+ 1;int x
= log2(len
);return min(dp
[l
][x
], dp
[r
- (1 << x
) + 1][x
]);}int findl(int pos
, int len
) {int l
= 1, r
= pos
;while (l
<= r
) {int mid
= (l
+ r
) >> 1;if (rmq(mid
, pos
) < len
) l
= mid
+ 1;else r
= mid
- 1;}return l
;}int findr(int pos
, int len
) {int l
= pos
, r
= n
;while (l
<= r
) {int mid
= (l
+ r
) >> 1;if (rmq(pos
, mid
) < len
) r
= mid
- 1;else l
= mid
+ 1;}return r
;}int solve(int ql
, int qr
, int k
) {int len
= qr
- ql
+ 1;int pos
= Rank
[ql
];int l
= findl(pos
, len
);int r
= findr(pos
, len
);if (r
- l
+ 1 < k
) return -1;return T
.query(T
.rt
[l
-1], T
.rt
[r
], 1, n
, k
);}
}S
;
int main() {ios
::sync_with_stdio(0);cin
.tie(0), cout
.tie(0);int T
;scanf("%d", &T
);while (T
--) {int n
, m
;scanf("%d %d", &n
, &m
);scanf("%s", s
+1);S
.init(s
, strlen(s
+1));S
.st();S
.build();int l
, r
, k
;for (int i
= 0; i
< m
; ++i
) {scanf("%d %d %d", &l
, &r
, &k
);printf("%d\n", S
.solve(l
, r
, k
));} }return 0;
}
與50位技術(shù)專家面對面20年技術(shù)見證,附贈技術(shù)全景圖
總結(jié)
以上是生活随笔為你收集整理的HDU - 6704 K-th occurrence (后缀数组+主席树)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。