随笔 - 531  文章 - 0  评论 - 3  阅读 - 10215 

把字符串S的所有后缀按照字典序排列,排名为 i 的后缀记为SA[ i ]

 

额外地,我们考虑排名为 i 的后缀与排名为  i-1 的后缀,把二者的最长公共前缀的长度记为 hgt[i]

使用快排、Hash 与二分 求出 两个数组

 

复制代码
#include<iostream>
#include <algorithm>
#include <cstring>
using namespace std;
 #define ll unsigned long long
  const int N=1e6+5;
  
 char s[N];
 int id[N],n;
 ll h[N],pow[N];
 ll bas=131;
 
 ll f1(int l,int r){
     return h[r]-h[l-1]*pow[r-l+1];
 }
 int find(int a,int b){
     int l=0,r=n-max(a,b)+1; int t=0;
         while(l<=r){
             int md=(l+r)/2;
             if(f1(a,a+md-1)==f1(b,b+md-1)) 
             l=md+1,t=md;
             else r=md-1;
         }
         return t;
 }
 int cmp(int i,int j){
     int k=find(i,j);
     int t1,t2;
     if(i+k<=n) t1=s[i+k]; else t1=-1e9;
     if(j+k<=n) t2=s[j+k]; else t2=-1e9;
     
     return t1<t2;
 }
 void sov(){
     h[0]=0; 
     int i,ans=0;
     n=strlen(s+1); 
     for(i=1;i<=n;i++){
         h[i]=h[i-1]*bas+s[i];
         id[i]=i;
     }
     sort(id+1,id+1+n,cmp);
     for(i=1;i<=n;i++) cout<<id[i]-1<<' ';
     cout<<endl<<0;
     for(i=2;i<=n;i++) cout<<' '<<find(id[i],id[i-1]);
     cout<<endl;
 }
 main(){
     int i;
     pow[0]=1;
     for(i=1;i<=1e6;i++) pow[i]=pow[i-1]*bas;
     cin>>s+1;
     sov();
 }
复制代码

 

posted on   towboat  阅读(18)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 展开说说关于C#中ORM框架的用法!
点击右上角即可分享
微信分享提示