trie上构建后缀数组和波兰表

普通后缀数组的倍增构建

​ 对于单个字符串上的后缀数组的建造,一般都是倍增一个长度 l ,然后对于当前的排序组,每隔 l 就把两个元素并在一起,拿这两个东西分别作为两个关键字再排序,直到倍增长度大于字符串长。其实这个倍增算法如果在trie上也是同样适用。

trie上后缀数组的倍增构建

​ 对于一个trie,我们同样可以通过倍增来求,只要把在序列上倍增 k 级变成树上的倍增 k 级祖先应该就可以了。如果我们把倍增的过程时的 rk 数组记录下来,我们就得到一个神奇的东西——用vfk的话来说就是波兰表。

​ 似乎在trie上SA建H数组有点不好搞,怎么办呢?没事,我们有波兰表!对于相邻的两个后缀,我们可以用记录下来的 k rk 的信息来搞,然后类似倍增那样判断其 k 级的排名是否相同,然后就可以求出LCP了。

​ 代码大概是这样:

void build() {
    rep (i , 1 , n) rk[i][0] = str[i];
    rep (i , 1 , n) pa[i][0] = fa[i];
    rep (j , 1 , lg) {
        rep (i , 1 , n)
            pos[i] = mp(mp(rk[i][j - 1] , rk[pa[i][j - 1]][j - 1]) , i) ,
            pa[i][j] = pa[pa[i][j - 1]][j - 1];
        sort(pos + 1 , pos + n + 1);
        rk[pos[1].sec][j] = 1;
        int p = 1;
        rep (i , 2 , n)
            rk[pos[i].sec][j] = (pos[i - 1].fir == pos[i].fir) ? p : ++ p;
    }
}

int LCP(int u , int v) {
    if (u == v)
        dep[u];
    int l = 0;
    per (i , lg , 0) if (rk[u][i] == rk[v][i]) {
        l += 1 << i;
        u = pa[u][i] , v = pa[v][i];
    }
    return l;
}

你可能感兴趣的:(trie上构建后缀数组和波兰表)