wls的数据结构-字典树

存储方式



字符集太大了,可以采用hash开字典树
log时间查询任意两个字符串的最大前缀
建字典树,然后查询lca
#include<bits/stdc++.h>

using namespace std;
typedef long long LL;
const int N = 5e5+10;
struct Node{
    int son[26];
    int depth;
}tr[N];
int f[N][20];
int tot, root;
int whed[N];
char s[10010];

void insert(int id, char s[]){
    int p = root;
    for(int i = 1; s[i]; i ++){
        int t = s[i] - 'a';
        if(!tr[p].son[t]){
            tr[p].son[t] = ++tot;
            tr[tot].depth = tr[p].depth + 1;
            f[tot][0] = p;
        }
        p = tr[p].son[t];
    }
    whed[id] = p;
}
int main(){
    int n; scanf("%d", &n);
    root = ++ tot;
    for(int i = 1; i <= n; i ++){
        scanf("%s", s + 1);
        insert(i, s);
    }
    // for(int i = 1; i <= tot; i ++) cout << f[i][0] << ' ';
    // cout << endl;
    for(int i = 1; i < 20; i ++){
        for(int j = 1; j <= tot; j ++){
            if(f[j][i - 1]) f[j][i] = f[f[j][i - 1]][i - 1];
        }
    }
    // cout << f[5][0] << "__" << endl;
    int q; scanf("%d", &q);
    while(q--){
        int x, y; scanf("%d %d", &x, &y);
        x = whed[x], y = whed[y];
        // cout << x << ' ' << y << endl;
        if(tr[x].depth < tr[y].depth) swap(x, y);
        int z = tr[x].depth - tr[y].depth;
        // cout << z << endl;
        for(int j = 20; j >= 0; j --){
            if(z >> j & 1) x = f[x][j];
        }
        // cout << x << ' ' << y << endl;8
        if(x == y){
            printf("%d\n", tr[x].depth);
            continue;
        }
        for(int j = 19; j >= 0; j --){
            // cout << x << ' ' << y << ' ' << f[x][j] << ' ' << f[y][j] << ' ' << "zz" << endl;
            if(f[x][j] != f[y][j]) x = f[x][j], y = f[y][j];
        }
        // cout << x << ' ' << y << ' ' << "zz" << endl;
        printf("%d\n", tr[f[x][0]].depth);
    }
    return 0;
}

posted @ 2022-04-02 12:20  牛佳文  阅读(52)  评论(0编辑  收藏  举报