后缀数组是什么?可以吃吗? 
不可以吃,它是给一个字符串的所有后缀进行排序的算法。 
如:一个字符串aabaaaab,它的后缀排好序后起始位置分别是:4 5 6 1 7 2 8 3 
显然如果暴力去排序时间复杂度为我才不会告诉你其实是我不会DC3算法呢)。 
接下来定义如下几个数组:
| 数组名 | 意义 | 
|---|---|
| 原串 | |
| 开头为 | 
引用大佬图解: 
 
倍增法的主要内容? 
每次对长度为
再次引用大佬图解: 
 
这张图是什么意思呢? 
就是:x和y分别作为第一关键字和第二关键字,进行排序,以这一次排序的结果作为下一次排序的参考。 
怎么排序? 
需要排序的范围不超过
时间复杂度? 
代码 
温馨提示:复制到记事本上并将tab键调成8格效果更佳
#include <cstdio>
#include <cstring>
const int maxn=100000;
char s[(maxn<<1)+10];
int sa[(maxn<<1)+10],rank[(maxn<<1)+10],tmp[(maxn<<1)+10];
int sum[(maxn<<1)+10],a[(maxn<<1)+10],n;
inline int swap(int *&x,int *&y)//指针swap
{
  int *t=x;
  x=y;
  y=t;
  return 0;
}
inline int suffix_sort()
{
  int *x=rank,*y=tmp,m=26;
  //先排序
  for(register int i=1; i<=n; ++i)
    {
      x[i]=a[i];
      y[i]=i;
      ++sum[x[i]];
    }
  for(register int i=1; i<=m; ++i)
    {
      sum[i]+=sum[i-1];
    }
  for(register int i=n; i; --i)
    {
      sa[sum[x[i]]]=i;
      --sum[x[i]];
    }
  int len=1,p=1;
  while(p<n)
    {
      m=p;
      p=0;
      //每次循环设一下初值,然后排序
      for(register int i=n-len+1; i<=n; ++i)
    {
      ++p;
      y[p]=i;
    }
      for(register int i=1; i<=n; ++i)
    {
      if(sa[i]-len>0)
        {
          ++p;
          y[p]=sa[i]-len;
        }
    }
    //前面是按第二关键字排序,接下来按第一关键字排序
      for(register int i=0; i<=m; ++i)
    {
      sum[i]=0;
    }
      for(register int i=1; i<=n; ++i)
    {
      ++sum[x[y[i]]];
    }
      for(register int i=1; i<=m; ++i)
    {
      sum[i]+=sum[i-1];
    }
      for(register int i=n; i; --i)
    {
      sa[sum[x[y[i]]]]=y[i];
      --sum[x[y[i]]];
    }
      swap(x,y);
      //现在y数组已经没有用了
      p=1;
      x[sa[1]]=1;
      //下一个步骤是去重
      for(register int i=2; i<=n; ++i)
    {
      if(!((y[sa[i-1]]==y[sa[i]])&&(y[sa[i-1]+len]==y[sa[i]+len])))
        {
          ++p;
        }
      x[sa[i]]=p;
    }
      len<<=1;
    }
  //如果所有的都已经排好序,那么就没有必要排下去了,退出
  p=0;
  //在上面计算的步骤中x数组记录的值可能不是真正的rank数组,需要重新计算
  for(register int i=1; i<=n; ++i)
    {
      ++p;
      rank[sa[i]]=p;
    }
  return 0;
}
int main()
{
  scanf("%s",s+1);
  n=strlen(s+1);
  for(register int i=1; i<=n; ++i)
    {
      a[i]=s[i]-'a'+1;
    }
  suffix_sort();
  for(register int i=1; i<=n; ++i)
    {
      printf("%d\n",sa[i]);
    }
  return 0;
}
 
                     
                    
                 
                    
                 
 
                
            
         
         浙公网安备 33010602011771号
浙公网安备 33010602011771号