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

普通后缀数组的倍增构建

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

trie上后缀数组的倍增构建

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

​ 似乎在trie上SA建H数组有点不好搞,怎么办呢?没事,我们有波兰表!对于相邻的两个后缀,我们可以用记录下来的 k rk的信息来搞,然后类似倍增那样判断其 k <script id="MathJax-Element-10" type="math/tex">k</script>级的排名是否相同,然后就可以求出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;
}
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值