后缀数组排序:
using namespace std;
const int N=1e5+10;
int n,k,p,q=1;
char ch[N];
int a[N],v[N],h[N],sa[2][N],rk[2][N];
void mul(int *sa,int *rk,int *SA,int *RK)
{
fo(i,1,n) v[rk[sa[i]]]=i;
for(int i=n;i;i--)
if(sa[i]>k)
SA[v[rk[sa[i]-k]]--]=sa[i]-k;
for(int i=n-k+1;i<=n;i++)
SA[v[rk[i]]--]=i;
fo(i,1,n) RK[SA[i]]=RK[SA[i-1]]+(rk[SA[i]]!=rk[SA[i-1]]||rk[SA[i]+k]!=rk[SA[i-1]+k]);
}
void presa()
{
for(int i=1;i<=n;i++)v[a[i]]++;
for(int i=1;i<=30;i++)v[i]+=v[i-1];
for(int i=1;i<=n;i++)
sa[p][v[a[i]]--]=i;
for(int i=1;i<=n;i++)
rk[p][sa[p][i]]=rk[p][sa[p][i-1]]+(a[sa[p][i-1]]!=a[sa[p][i]]);
for(k=1;k<n;k<<=1,swap(p,q))
mul(sa[p],rk[p],sa[q],rk[q]);
for(int i=1,k=0;i<=n;i++)
{
int j=sa[p][rk[p][i]-1];
while(a[i+k]==a[j+k])k++;
h[rk[p][i]]=k;if(k>0)k--;
}
}
int main()
{
scanf("%s",ch+1);
n=strlen(ch+1);
fo(i,1,n) a[i]=ch[i]-'a'+1;
presa();
fo(i,1,n) printf("%d ",sa[p][i]); puts("");
fo(i,2,n) printf("%d ",h[i]); puts("");
return 0;
}
树剖
using namespace std;
const int N=3e4+10,M=6e4+10,inf=(1<<30);
int n,q,
pos[N],v[N],dep[N],fa[N],size[N],bl[N],
head[N],len,sz;
struct Edge{int to,next;Edge(int to=0,int next=0):to(to),next(next){}}e[M];
void add_edge(int from,int to){ e[++len]=Edge(to,head[from]); head[from]=len;}
struct Seg
{
int l,r,mx,sum;
}t[N<<2];
void init()
{
scanf("%d",&n);
for(int from,to,i=1;i<n;i++)
{
scanf("%d%d",&from,&to);
add_edge(from,to);
add_edge(to,from);
}
fo(i,1,n) scanf("%d",&v[i]);
}
void dfs1(int x)
{
size[x]=1;
for(int i=head[x];i;i=e[i].next) {
int id=e[i].to;
if(id==fa[x]) continue;
fa[id]=x;
dep[id]=dep[x]+1;
dfs1(id);
size[id]+=size[x];
}
}
void dfs2(int x,int chain)
{
int k=0; pos[x]=++sz;
bl[x]=chain;
for(int i=head[x];i;i=e[i].next) {
int id=e[i].to;
if(dep[id]>dep[x]&&size[id]>size[k]) k=id;
}
if(k==0) return ;
dfs2(k,chain);
for(int i=head[x];i;i=e[i].next) {
int id=e[i].to;
if(dep[id]>dep[x]&&k!=id)
dfs2(id,id);
}
}
void build(int k,int l,int r)
{
t[k].l=l; t[k].r=r;
if(l==r) return ;
int mid=(l+r)>>1;
build(k<<1,l,mid);
build(k<<1|1,mid+1,r);
}
void change(int k,int x,int y)
{
int l=t[k].l,r=t[k].r,mid=(l+r)>>1;
if(l==r) {t[k].mx=t[k].sum=y;return ;}
if(x<=mid) change(k<<1,x,y);
else change(k<<1|1,x,y);
t[k].sum=t[k<<1].sum+t[k<<1|1].sum;
t[k].mx=max(t[k<<1].mx,t[k<<1|1].mx);
}
int querysum(int k,int x,int y)
{
int l=t[k].l,r=t[k].r,mid=(l+r)>>1;
if(l==x&&y==r) return t[k].sum;
if(y<=mid) return querysum(k<<1,x,y);
else if(x>mid) return querysum(k<<1|1,x,y);
else {return querysum(k<<1,x,mid)+querysum(k<<1|1,mid+1,y);}
}
int querymax(int k,int x,int y)
{
int l=t[k].l,r=t[k].r,mid=(l+r)>>1;
if(l==x&&y==r) return t[k].mx;
if(y<=mid) return querymax(k<<1,x,y);
else if(x>mid) return querymax(k<<1|1,x,y);
else {return max(querymax(k<<1,x,mid),querymax(k<<1|1,mid+1,y));}
}
int solvesum(int x,int y)
{
int sum=0;
while(bl[x]!=bl[y]) {
if(dep[bl[x]]<dep[bl[y]]) swap(x,y);
sum+=querysum(1,pos[bl[x]],pos[x]);
x=fa[bl[x]];
}
if(pos[x]>pos[y]) swap(x,y);
sum+=querysum(1,pos[x],pos[y]);
return sum;
}
int solvemx(int x,int y)
{
int mx=-inf;
while(bl[x]!=bl[y]) {
if(dep[bl[x]]<dep[bl[y]]) swap(x,y);
mx=max(querymax(1,pos[bl[x]],pos[x]),mx);
x=fa[bl[x]];
}
if(pos[x]>pos[y]) swap(x,y);
mx=max(mx,querymax(1,pos[x],pos[y]));
return mx;
}
void solve()
{
build(1,1,n);
fo(i,1,n) change(1,pos[i],v[i]);
scanf("%d",&q);
char ch[10];
for(int x,y,i=1;i<=q;i++) {
scanf("%s%d%d",ch,&x,&y);
if(ch[0]=='C') {v[x]=y;change(1,pos[x],y);}
else {
if(ch[1]=='M') printf("%d\n",solvemx(x,y));
else printf("%d\n",solvesum(x,y));
}
}
}
int main()
{
init();
dfs1(1);
dfs2(1,1);
solve();
return 0;
}