如果需要動態維護字尾陣列,支援在字串前端插入乙個字元,詢問字尾的大小關係,如何做呢?
這是乙個不斷插入的問題,可以從增量的角度考慮。我們在前端插入乙個字元,其實就是插入了乙個新的字尾。我們的問題其實就是這個字尾排名多少。我們可以用平衡樹維護一下字尾陣列,從根節點開始二分比較這個字尾的大小,看看它應該被插到**。現在問題就變成了快速比較乙個新的字尾和乙個已有的字尾。
如果這個新的字尾和當前比較的字尾的首字元不同,那麼比較結果是顯然的;如果新的字尾和當前比較的字尾的首字元相同,那麼問題就轉化成了比較原來已有的兩個字尾的大小關係。我們在平衡樹的每個節點上維護乙個值\(x\in [0,1]\),代表它的大小,左兒子為的關鍵值為\([l,mid]\),右兒子的關鍵值為\([mid,r]\),那麼只要直接比較這個值就可以啦。
然而如果平衡樹的深度過大,那麼這個值會爆實數的精度。所以我們採用深度為\(o(logn)\)的平衡樹。但如果平衡樹需要旋轉,那麼它的子樹需要全部重新計算關鍵值。所以我們需要使用重量平衡樹,其子樹大小均攤\(o(logn)\),所以每次插入旋轉後整個子樹重算一下。
**:
#include#include#include#include#include#includeusing namespace std;
typedef long long giant;
int read()
const int maxn=3e5+1;
const int p=1e9+7;
char start[maxn];
int ans=0,len,type,ansh=0;
int convert(int x)
struct node
};struct sat
int newnode()
void revalue(int x,double lx,double rx)
bool rson(int x)
void getval(int x)
void rotate(int x)
bool compare(int x,int y)
int query(int x,int y) else if (op[0]=='q')
} printf("%d\n",ansh);
return 0;
}
字尾平衡樹學習筆記
給定乙個空串s 操作1 代表在 s前加入乙個字母使之成為新s 操作2 代表在詢問在當前 s中有多少連續子串等於給定串t 假設我們已經有了串 s的字尾平衡樹 插入乙個字母c 我們用s i代表原串 s 從第 i個字元開始的字尾 則字尾 cs 與 任意乙個字尾 si 的大小關係可以用 c與s i 的第乙個...
總結 字尾平衡樹學習筆記
字尾平衡樹,就是動態的維護字尾陣列,可以 o log n 在末尾插入字元,o log n 查詢 rank,sa 但是由於是維護的字尾資訊,所以插入只能在末尾插入字元 然後轉化成在開頭加乙個字元 相當於新增乙個字尾。方法一 我們需要一種能比較兩個字尾大小的方法,最簡單就是二分 hash,o log n...
BZOJ3682 Phorni 字尾平衡樹
傳送門 字尾平衡樹模板題 用平衡樹維護每乙個字尾的排名 關鍵在於查詢兩個字尾的大小 可以用二分加hash,複雜度 log 2n log 2n log2 n 插入 或者 每次前面插入乙個字元,先比較兩個字尾第乙個字元的大小 而後面的大小我們已經在平衡樹上維護好了 像這樣分配權值 給樹上每個子樹乙個實數...