最長公共前綴(lca+trie樹)


問題描述

給出一些串,多組詢問求兩個串的最長公共前綴。字符串總長 < 10^6。

輸入格式

第一行一個整數n,表示字符串的個數。

接下來n行,每行一個字符串(字符串不含空格)。

第n+2行一個整數m,表示詢問總數。

接下來m行,每行兩個整數a,b,表示詢問第a個字符串和第b個字符串的最長公共前綴的長度。

輸出格式

輸出共m行,對於每個詢問輸出最長的公共前綴的長度

輸入樣例

5
abcdef
abcd
acd
cade
abcdef
4
1 2
2 3
1 5
3 4

輸出樣例

4
1
6
0

限制與約定

1<= m < 10^6

時間限制:1s

空間限制:256MB

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
using namespace std;
const int maxn = 1000000 + 10 ;
int n,ch[maxn][30],val[maxn],cnt,m;
int f[maxn][31],Dep[maxn];
string str[30010];
void dfs(int u,int fa)
{
    Dep[u]=Dep[fa]+1;
    for(int i=0;i<=29;i++) f[u][i+1]=f[f[u][i]][i];
    for(int i=0;i<=26;i++)
    {
        int v = ch[u][i];
        if(!v) continue;
        f[v][0]=u;
        dfs(v,u);
    }
}
void insert(int pos)
{
    int len = str[pos].length(),u=0;
    for(int i=0;i<len;i++)
    {
        int x = str[pos][i]-'a';
        if(!ch[u][x]) ch[u][x]=++cnt;
        u=ch[u][x];
    }
    val[pos]=u;
}
int LCA(int x,int y)
{
    if(Dep[x]<Dep[y]) swap(x,y);
    for(int i=30;i>=0;i--)
    {
        if(Dep[f[x][i]]>=Dep[y]) x=f[x][i];
        if(x==y) return x;
    }
    for(int i=30;i>=0;i--)
        if(f[x][i]!=f[y][i])
        {
            x=f[x][i];
            y=f[y][i];
        }
    return f[x][0];
}
int main()
{
    cin>>n;
    for(int i=1;i<=n;i++)
    {
        cin>>str[i];
        insert(i);
    }
    dfs(0,-1);
    cin>>m;
    for(int i=1,a,b;i<=m;i++)
    {
        scanf("%d%d",&a,&b);
        int lca=LCA(val[a],val[b]);
        printf("%d\n",Dep[lca]-1);
    }
    return 0;
}

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM