日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

B-Suffix Array

發布時間:2023/12/3 编程问答 30 豆豆
生活随笔 收集整理的這篇文章主要介紹了 B-Suffix Array 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

B-Suffix Array

題意:

一個字符串只含有a和b,先給出b數組的構造方式:
對于每個位置i來說:

  • 如果存在一個位置j,使得j<i,且s[j] == s[i],則b[i]=i-j
  • 否則b[i]=0
    現在對字符串每個后綴都構造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的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。