问题描述
给出一些串,多组询问求两个串的最长公共前缀。字符串总长 < 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; }