B-Suffix Array
生活随笔
收集整理的這篇文章主要介紹了
B-Suffix Array
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
B-Suffix Array
題意:
一個字符串只含有a和b,先給出b數組的構造方式:
對于每個位置i來說:
現在對字符串每個后綴都構造B數組,并按照字典序排序
題解:
參考博客
題目標題就已經透露了一切,Suffix Array,說明這個題要用后綴數組來做,但是具體怎么做呢?
我們會發現,化為B數組的值后,第一個a的值肯定為0,第一個b的值肯定也為0,那么從第一個a到第一個b之間肯定都是1
比如“aaaabaaab”,則B(t) = 011102114,前半段為01110(也就是第一個a到第一個b),我們可以將B數組分為兩部分,前半部為01110,后半部分為2114,這樣字典序排序時,我們先對前半部分排序即可,如果前半部分一樣再對后半部分排序
對于前半部分排序,直接比較長度即可,因為都是0開頭,0結尾,中間是1,越長說明中間的1越多,且前半部分極好確定,直接找第一個a與b就行
那現在后半部分怎么確定呢?
Ai表示前半部分,DI表示后半部分
后半部分是數組B的后綴,我們直接后綴數組,得到rank值,rank[i+|Ai|]就是Di的排名
Rank[i]=后綴suf(i)的排名,也就是從第i位到最后一位構成的子串排名
這個題,秒極了
代碼:
#include <bits/stdc++.h> using namespace std; struct _IO{_IO(){ios::sync_with_stdio(0);cin.tie(0);}}_io; typedef long long ll; typedef long double db; const int N = 2e6 + 5, M = 1e9 + 7;int sa[N], rk[N], oldrk[N << 1], id[N], px[N], cnt[N]; // px[i] = rk[id[i]](用于排序的數組所以叫 px)bool cmp(int x, int y, int w) {return oldrk[x] == oldrk[y] && oldrk[x + w] == oldrk[y + w]; }void da(int *s, int n, int m) {int i,p,w;for(int i=0;i<=n;i++)cnt[i]=0;for (i = 1; i <= n; ++i) ++cnt[rk[i] = s[i]];for (i = 1; i <= m; ++i) cnt[i] += cnt[i - 1];for (i = n; i >= 1; --i) sa[cnt[rk[i]]--] = i;for (w = 1; w < n; w <<= 1, m = p) { // m=p 就是優化計數排序值域for (p = 0, i = n; i > n - w; --i) id[++p] = i;for (i = 1; i <= n; ++i)if (sa[i] > w) id[++p] = sa[i] - w;//memset(cnt, 0, sizeof(cnt));for(int i=0;i<=n;i++)cnt[i]=0;for (i = 1; i <= n; ++i) ++cnt[px[i] = rk[id[i]]];for (i = 1; i <= m; ++i) cnt[i] += cnt[i - 1];for (i = n; i >= 1; --i) sa[cnt[px[i]]--] = id[i];for(int i=0;i<=n;i++)oldrk[i]=rk[i];//memcpy(oldrk, rk, sizeof(rk));for (p = 0, i = 1; i <= n; ++i)rk[sa[i]] = cmp(sa[i], sa[i - 1], w) ? p : ++p;}}int n; struct node {int x, y;bool operator < (const node &b) const {if (y - x == b.y - b.x) {return rk[y+1] < rk[b.y+1];}return y - x < b.y - b.x;} } a[N]; int b[N]; char s[N]; int main() {while (cin >> n) {cin >> s+1;int x = -1, y = -1;for (int i = 1; i <= n; i++) {b[i] = 0;if (s[i] == 'a') {if (x != -1) b[i] = i - x;x = i;} else {if (y != -1) b[i] = i - y;y = i;}}for(int i=1;i<=n;i++){b[i]++;}da(b, n, n);//后綴數組求出rank數組for(int i=1;i<=n;i++)x = y = n+1;for (int i = n ; i >= 1; i--) {if (s[i] == 'a') {//從第i位開始的后綴,分為前部分Ai,范圍[x,y]和后部分Bi a[i] = {i, y};x = i;} else {a[i] = {i, x};y = i;}}rk[n+1] = -1;rk[n+2] = -2;sort(a+1, a + n+1);for (int i = 1; i <=n; i++) {cout << a[i].x << ' ';}cout << '\n';} }總結
以上是生活随笔為你收集整理的B-Suffix Array的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: H.Minimum-cost Flow
- 下一篇: Android绘图(一)基础篇