变量
- int k1[i]:第一关键字。
- int k2[i]:第二关键字。
- int c[i]:第 i 个关键字出现的次数。
- int sa[i]:排名为 i 的后缀的编号。
函数
- void qsa(int n,int m,string s):求长度为 n,字符串种类为 1∼m 的字符串 s 的 SA 数组(下标从 1 开始)。
代码
struct SA{
int k1[N],k2[N],c[N],sa[N],rk[N],h[N];
void qsa(int n,int m,string s){
for(int i=1;i<=n;i++)c[k1[i]=s[i]]++;
for(int i=1;i<=m;i++)c[i]+=c[i-1];
for(int i=1;i<=n;i++)sa[c[k1[i]]--]=i;
for(int b=1,tot;b<=n;b<<=1){
tot=0;
for(int i=n-b+1;i<=n;i++)k2[++tot]=i;
for(int i=1;i<=n;i++)
if(sa[i]>b)k2[++tot]=sa[i]-b;
for(int i=1;i<=m;i++)c[i]=0;
for(int i=1;i<=n;i++)c[k1[i]]++;
for(int i=1;i<=m;i++)c[i]+=c[i-1];
for(int i=n;i>=1;i--)
sa[c[k1[k2[i]]]--]=k2[i],k2[i]=0;
swap(k1,k2);tot=1;k1[sa[1]]=1;
for(int i=2;i<=n;i++)
if(k2[sa[i]]==k2[sa[i-1]]&&k2[sa[i]+b]==k2[sa[i-1]+b])
k1[sa[i]]=tot;
else k1[sa[i]]=++tot;
if(tot==n)return;
m=tot;
}
for(int i=1;i<=n;i++)rk[sa[i]]=i;
for(int i=1,k=0;i<=n;i++){
if(k)k--;
while(s[i+k]==s[sa[rk[i]-1]+k])k++;
h[rk[i]]=k;
}
}
}st;