博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
[模板]后缀数组
阅读量:4510 次
发布时间:2019-06-08

本文共 1325 字,大约阅读时间需要 4 分钟。

原理

定义rank[i]表示suffix[i]在所有后缀中的字典序排名;sa[i]表示字典序排名为i的后缀是suffix[sa[i]]

定义height[i]表示排名为i的后缀和排名为i-1的后缀的LCP(最长公共前缀)

可以证明,$height[rank[i]]>=height[rank[i-1]]-1$

然后有对于两个后缀x,y,$LCP(x,y)=min_{i \in (rank[x],rank[y]]}{height[i]}$

所以预处理一个ST表就可以O(1)查LCP了

做法

可以用倍增+基数排序来求

具体怎么做还是背板子吧2333

1 inline void build(){ 2     for(int i=1;i<=N;i++) cnt[s[i]]=1; 3     for(int i=1;i<=M;i++) cnt[i]+=cnt[i-1]; 4     for(int i=N;i;i--) rnk[i]=cnt[s[i]]; 5     for(int j=-1,l=1;j!=N;l<<=1){ 6         CLR(cnt,0); 7         for(int i=1;i<=N;i++) cnt[rnk[i+l]]++; 8         for(int i=1;i<=M;i++) cnt[i]+=cnt[i-1]; 9         for(int i=N;i;i--) tmp[cnt[rnk[i+l]]--]=i;10         CLR(cnt,0);11         for(int i=1;i<=N;i++) cnt[rnk[i]]++;12         for(int i=1;i<=M;i++) cnt[i]+=cnt[i-1];13         for(int i=N;i;i--) sa[cnt[rnk[tmp[i]]]--]=tmp[i];14         memcpy(tmp,rnk,sizeof(tmp));15         rnk[sa[1]]=j=1;16         for(int i=2;i<=N;i++){17             if(tmp[sa[i]]!=tmp[sa[i-1]]||tmp[sa[i]+l]!=tmp[sa[i-1]+l]) j++;18             rnk[sa[i]]=j;19         }M=j;20     }21     22     for(int i=1,j=0;i<=N;i++){23         if(rnk[i]==1) continue;24         if(j) j--;25         int x=sa[rnk[i]-1];26         while(x+j<=N&&i+j<=N&&s[x+j]==s[i+j]) j++;27         hei[rnk[i]]=j;28     }29 }

注意rank和tmp开两倍空间

转载于:https://www.cnblogs.com/Ressed/p/9677707.html

你可能感兴趣的文章
一、python特性+python安装测试
查看>>
Windows下安装Ubuntu16.04双系统
查看>>
Windows文件操作基础代码
查看>>
1-8
查看>>
任务17:从UML角度来理解依赖
查看>>
阶段1 语言基础+高级_1-3-Java语言高级_04-集合_04 数据结构_2_数据结构_队列
查看>>
Entity Framework操作Oracle数据库实现主键自增问题
查看>>
Leetcode WC-108-03 931-下降路径最小和
查看>>
从“智猪博弈”看所谓“大国责任”
查看>>
Day3:Spring-JDBC、事务管理
查看>>
模块的四种形式
查看>>
教你如何培养幽默感
查看>>
asp.net的一个简单简历缓存方法
查看>>
loj 1185(bfs)
查看>>
HTML5 (三)本地存储
查看>>
全排列-按从大到小-time limited
查看>>
nginx https使用
查看>>
task_13
查看>>
linux下删除特殊符号
查看>>
大话设计模式--责任链模式
查看>>