分析:将n字符串拼接后求出后缀数组,当查询x和y时,即是求height[i]到height[j]之间的最小值,ij为xy对应的排名。
这里height的最小值可以用线段树维护也可以用st表来维护(为啥我用线段树比st表快??)
ST表代码:
#include "cstdio"
#include "cstring"
#include "iostream"
#include "algorithm"
#include "bits/stdc++.h"
using namespace std;
int s[1100010];
char ts[1100010];
int sa[1100010],x[1100010],y[1100010],c[1100010],n,m,height[1100010],rk[1100010];
void Suffix(){
for(int i=0;i<m;i++) c[i]=0;
for(int i=0;i<n;i++) c[x[i]=s[i]]++;
for(int i=0;i<m;i++) c[i]+=c[i-1];
for(int i=n-1;i>=0;i--) sa[--c[x[i]]]=i;
for(int k=1;k<=n;k<<=1) {
int p=0;
for(int i=n-k;i<n;i++) y[p++]=i;
for(int i=0;i<n;i++) if(sa[i]>=k) y[p++]=sa[i]-k;
for(int i=0;i<m;i++) c[i]=0;
for(int i=0;i<n;i++) c[x[y[i]]]++;
for(int i=0;i<m;i++) c[i]+=c[i-1];
for(int i=n-1;i>=0;i--) sa[--c[x[y[i]]]]=y[i];
swap(x,y);
p=1;x[sa[0]]=0;
for(int i=1;i<n;i++)
x[sa[i]]= y[sa[i]]==y[sa[i-1]]&&y[sa[i]+k]==y[sa[i-1]+k]?p-1:p++;
if(p>=n) break;
m=p;
}
}
void getheight(){
for(int i=0;i<n;i++) rk[sa[i]]=i;
for(int i=0,k=0;i<n;i++){
if(rk[i]){
if(k) --k;
else k=0;
int j=sa[rk[i]-1];
while(s[i+k]==s[j+k]) k++;
height[rk[i]]=k;
}
}
}
//////////////////////////////////////////////////////////////////////////////////////
int dp[2000004][40];
int be[100004];
void init(){
//memset(dp,0x3f3f3f3f, sizeof(dp));
for (int i = 0; i < n; ++i) {
dp[i][0]=height[i];
}
for (int j = 1; (1<<j) < n; ++j) {
for (int i = 0; i + (1<<j) - 1 < n; ++i) {
dp[i][j]=0x3f3f3f3f;
dp[i][j]=min(dp[i][j-1],dp[i+(1<<j-1)][j-1]);
}
}
}
int que(int l,int r){
int k = log2(r-l+1);
return min(dp[l][k],dp[r-(1<<k)+1][k]);
}
int LEN[100004];
int main(){
int t;
cin>>t;
int kase = 1;
while(t--){
int N;
cin>>N;
m = 30;
n = 0;
for (int i = 0; i < N; ++i) {
scanf("%s",ts);
int len = strlen(ts);
LEN[i+1]=len;
be[i+1]=n;
for (int j = 0; j < len; ++j) {
s[n++]=ts[j]-'a'+1;
}
s[n++]=m++;
}
s[n++]=0;
Suffix();
getheight();
int q;
cin>>q;
init();
printf("Case %d:\n",kase++);
while(q--){
int x,y;
scanf("%d%d",&x,&y);
if(x==y){
printf("%d\n",LEN[x]);
continue;
}
x = rk[be[x]];
y = rk[be[y]];
if(x>y)swap(x,y);
printf("%d\n",que(x+1,y));
}
}
}
线段树:
#include "cstdio"
#include "cstring"
#include "iostream"
#include "algorithm"
#include "bits/stdc++.h"
using namespace std;
int s[1100010];
char ts[1100010];
int sa[1100010],x[1100010],y[1100010],c[1100010],n,m,height[1100010],rk[1100010];
void Suffix(){
for(int i=0;i<m;i++) c[i]=0;
for(int i=0;i<n;i++) c[x[i]=s[i]]++;
for(int i=0;i<m;i++) c[i]+=c[i-1];
for(int i=n-1;i>=0;i--) sa[--c[x[i]]]=i;
for(int k=1;k<=n;k<<=1) {
int p=0;
for(int i=n-k;i<n;i++) y[p++]=i;
for(int i=0;i<n;i++) if(sa[i]>=k) y[p++]=sa[i]-k;
for(int i=0;i<m;i++) c[i]=0;
for(int i=0;i<n;i++) c[x[y[i]]]++;
for(int i=0;i<m;i++) c[i]+=c[i-1];
for(int i=n-1;i>=0;i--) sa[--c[x[y[i]]]]=y[i];
swap(x,y);
p=1;x[sa[0]]=0;
for(int i=1;i<n;i++)
x[sa[i]]= y[sa[i]]==y[sa[i-1]]&&y[sa[i]+k]==y[sa[i-1]+k]?p-1:p++;
if(p>=n) break;
m=p;
}
}
void getheight(){
for(int i=0;i<n;i++) rk[sa[i]]=i;
for(int i=0,k=0;i<n;i++){
if(rk[i]){
if(k) --k;
else k=0;
int j=sa[rk[i]-1];
while(s[i+k]==s[j+k]) k++;
height[rk[i]]=k;
}
}
}
//////////////////////////////////////////////////////////////////////////////////////
struct node
{
int l,r,w;
}t[4100010];
int be[100004];
void b(int rt,int l,int r){
t[rt].l=l,t[rt].r=r;
if(l==r){
t[rt].w=height[l];
}
else {
int mid = (l+r)>>1;
b(rt<<1,l,mid),b(rt<<1|1,mid+1,r);
t[rt].w=min(t[rt<<1].w,t[rt<<1|1].w);
}
}
int que(int rt,int l,int r){
if(t[rt].l>=l&&t[rt].r<=r)return t[rt].w;
else {
int res = 2e9;
int mid = (t[rt].l+t[rt].r)>>1;
if(l<=mid)res=min(res,que(rt<<1,l,r));
if(r>mid)res=min(res,que(rt<<1|1,l,r));
return res;
}
}
int LEN[100004];
int main(){
int t;
cin>>t;
int kase = 1;
while(t--){
int N;
cin>>N;
m = 30;
n = 0;
for (int i = 0; i < N; ++i) {
scanf("%s",ts);
int len = strlen(ts);
LEN[i+1]=len;
be[i+1]=n;
for (int j = 0; j < len; ++j) {
s[n++]=ts[j]-'a'+1;
}
s[n++]=m++;
}
s[n++]=0;
Suffix();
getheight();
int q;
cin>>q;
b(1,0,n-1);
printf("Case %d:\n",kase++);
while(q--){
int x,y;
scanf("%d%d",&x,&y);
if(x==y){
printf("%d\n",LEN[x]);
continue;
}
x = rk[be[x]];
y = rk[be[y]];
if(x>y)swap(x,y);
printf("%d\n",que(1,x+1,y));
}
}
}