# 【模板题】后缀排序

### 限制与约定

$1 \leq n \leq 10^5$

aacca

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstdlib>
#include<cstring>
#include<string>
#include<climits>
#include<vector>
#include<cmath>
#include<map>
#define LL long long

using namespace std;

inline char nc(){
static char buf[100000],*p1=buf,*p2=buf;
if (p1==p2) { p2=(p1=buf)+fread(buf,1,100000,stdin); if (p1==p2) return EOF; }
return *p1++;
}

char c=nc();int b=1;
for (;!(c>='0' && c<='9');c=nc()) if (c=='-') b=-1;
for (x=0;c>='0' && c<='9';x=x*10+c-'0',c=nc()); x*=b;
}

char c=nc();LL b=1;
for (;!(c>='0' && c<='9');c=nc()) if (c=='-') b=-1;
for (x=0;c>='0' && c<='9';x=x*10+c-'0',c=nc()); x*=b;
}
{
char c=nc();int len=0;
for(;!((c>='A' && c<='Z')||(c>='a' && c<='z'));c=nc()) if (c==EOF) return 0;
for(;((c>='A' && c<='Z')||(c>='a' && c<='z'));s[len++]=c,c=nc());
s[len++]='\0';
return len;
}
for (x=nc();!(x=='?' || x=='+' || x=='-');x=nc());
}
int wt,ss[19];
inline void print(int x){
if (x<0) x=-x,putchar('-');
if (!x) putchar(48); else {
for (wt=0;x;ss[++wt]=x%10,x/=10);
for (;wt;putchar(ss[wt]+48),wt--);}
}
inline void print(LL x){
if (x<0) x=-x,putchar('-');
if (!x) putchar(48); else {for (wt=0;x;ss[++wt]=x%10,x/=10);for (;wt;putchar(ss[wt]+48),wt--);}
}
int n,m,s,b[200010],c[200010],d[200010];
char sx[200010],sy[200010];
struct data
{
int len,fa,letter[26],tree[26],id,flag;
}a[200010];
int sa[200010],rank[200010],RANK;
void Extend(int x,int p)
{
s++;int q=s;a[q].len=a[p].len+1;
while (p!=0 && a[p].letter[x]==0)
a[p].letter[x]=q,p=a[p].fa;
if (p==0) {a[q].fa=1;return ;}
int np=a[p].letter[x];
if (a[np].len==a[p].len+1) a[q].fa=np;
else
{
s++;int nq=s;a[nq].len=a[p].len+1;
for (int i=0;i<26;i++)
a[nq].letter[i]=a[np].letter[i];
a[nq].id=a[np].id;
a[nq].fa=a[np].fa;a[np].fa=nq;a[q].fa=nq;
while (p!=0&&a[p].letter[x]==np)
a[p].letter[x]=nq,p=a[p].fa;
}
}
void Insert(char x[])
{
int y=strlen(x);
s=1;int z=1;
for (int i=y-1;i>=0;i--)
Extend(x[i]-'a',z),z=a[z].letter[x[i]-'a'],a[z].id=i+1,d[i+1]=z,a[z].flag=1;
}
void dfs(int x)
{
if(a[x].id!=0 && a[x].flag) sa[++RANK]=a[x].id,rank[a[x].id]=RANK;
for (int i=0;i<26;i++)
if (a[x].tree[i]!=0) dfs(a[x].tree[i]);
}
void build()
{
for (int i=1;i<=s;i++)
c[a[i].len]++;
for (int i=1;i<=s;i++)
c[i]+=c[i-1];
for (int i=1;i<=s;i++)
b[c[a[i].len]--]=i;
for (int i=s;i>=1;i--)
{
int p=b[i];
a[a[p].fa].tree[sx[a[p].id+a[a[p].fa].len-1]-'a']=p;
}
RANK=0;
dfs(1);
}
LL Query(int x,int y)
{
if (x==y) return a[x].len;
if (a[x].len>a[y].len) return Query(a[x].fa,y);
else return Query(x,a[y].fa);
}
int main()
{