后缀数组学习笔记

现在来看倍增算法是非常好理解的。

直接放一篇blog写的挺好的:http://www.cnblogs.com/zinthos/p/3899725.html

虽然理论复杂度是$O(nlogn)$,但其中各种细节优化确实十分有必要的。

给自己放一个倍增的模板,有空填DC3的坑

 1 #include<cstdio>
 2 #include<cstring>
 3 #include<algorithm>
 4 using namespace std;
 5 int n,m;
 6 char s[1000010];
 7 int rk[1000010],sa[1000010],tmp[1000010],c[1000010];
 8 void outint(int x){
 9     if(x>=10) outint(x/10);
10     putchar(x%10+‘0‘);
11 }
12 bool inline cmp(int *r,int a,int b,int l){
13     return r[a]==r[b]&&r[a+l]==r[b+l];
14 }
15 void Getsa(){
16     m=127;
17     for(int i=0;i<=m;i++) c[i]=0;
18     for(int i=1;i<=n;i++) c[rk[i]=s[i]]++;
19     for(int i=1;i<=m;i++) c[i]+=c[i-1];
20     for(int i=n;i>=1;i--) sa[c[rk[i]]--]=i;
21     for(int i=1;i<=n;i<<=1){
22         int p=0;
23         for(int j=n-i+1;j<=n;j++) tmp[++p]=j;
24         for(int j=1;j<=n;j++) if(sa[j]>i) tmp[++p]=sa[j]-i;
25         for(int j=0;j<=m;j++) c[j]=0;
26         for(int j=1;j<=n;j++) c[rk[tmp[j]]]++;
27         for(int j=1;j<=m;j++) c[j]+=c[j-1];
28         for(int j=n;j>=1;j--) sa[c[rk[tmp[j]]]--]=tmp[j];
29         swap(rk,tmp);
30         rk[sa[1]]=p=1;
31         for(int j=2;j<=n;j++) rk[sa[j]]=cmp(tmp,sa[j],sa[j-1],i)?p:++p;
32         if(p>=n) break;
33         m=p;
34     }
35 }
36 int main(){
37     scanf("%s",s+1);
38     n=strlen(s+1);
39     Getsa();
40     for(int i=1;i<=n;i++){
41         outint(sa[i]);
42         putchar(‘ ‘);
43     }
44     return 0;
45 }
时间: 2024-10-26 00:03:11

后缀数组学习笔记的相关文章

后缀数组学习笔记【详解|图】

后缀数组学习笔记[详解] 老天,一个后缀数组不知道看了多少天,最后终于还是看懂了啊! 最关键的就是一会儿下标表示排名,一会用数值表示排名绕死人了. 我不知道手跑了多少次才明白过来.其实我也建议初学者手跑几遍,但是一定要注意数组的意义,否则就是无用功. 数组含义: s[ ]:输入的字符串,预处理的时候会在末尾加上一个0 sa[ ]:它的下标就是后缀排名 x[ ] = t[ ]:用来保存第一关键字排名,注意!它的数值是排名.初始时恰好是字符串的ASCII码.字典序嘛! y[ ] = t2[ ]:它的

蓝鸥Unity开发基础—— 一维数组学习笔记

蓝鸥Unity开发基础-- 一维数组学习笔记 一.数组 之前我们学过很多数据类型,今天我们来学习数字,数字也是一种数据类型,那么,具体的数组是如何定义的? 数组:相同数据类型的成员组成的一组数据 Int类型数组:4  7  12  3  5--数组元素 Float数据类型数字:11.5 4.62 7.1 2.21 9.3--数组元素 数组中每一个元素都会分配一个数组下标,数组下标是从0开始的,有序排列,如:0 1 2 3 4 二.声明并初始化数组: 数组也是数据类型,所以也可以声明变量.使用ne

蓝鸥Unity开发基础—— 二维数组学习笔记

蓝鸥Unity开发基础-- 二维数组学习笔记 一.二维数组 有两个下标的数组叫做二维数组 类似[,]数组名=new类型[常量表达式1,常量表达式2] int[,] numbers= new int[2,3]; [0,0] [0,1] [0,2] [1,0] [1,1] [1,2] 举例说明 using System; namespace Lesson16{    class MainClass    {        public static void Main (string[] args)

勾股数组 学习笔记

颓废了一个暑假,想做点CF提高一下智商,然后就被这题卡住了.    http://codeforces.com/contest/707/problem/C 题目大意是给出各条边都是正整数的直角三角形的一条边长,求另外两条边可能的一种方案. 除了爆搜脑子一片空白,然后就很没志气的看了题解,提到了勾股数组,于是学习了一下.网络上的资料感觉证明不是详细,所以自己来写个总结. 1.首先如果 $a^2+b^2=c^2$ , 则$(ka)^2+(kb)^2=(kc)^2$ , 因此我们先只考虑$gcd(a,

《C#高级编程》【第六章】数组 -- 学习笔记

       为了解决大量的同类型元素,于是数组就孕育而生了.数组是具有一定顺序关系的若干对象的集合体,一维数组可以看作是定长的线性表.反之,n为的数组可以看作线性表的推广.从存储结构上来看,数组是一段连续的存储空间.现在我们看看在C#中的数组: 1.普通数组 在C#中普通数组又可以分为一维数组.多维数组和锯齿数组. <1>一维数组 我们现在先看看一维数组的声明语法: 类型[] 变量名; 知道怎么声明了,现在我们继续看看数组的初始化吧,在C#中有4种初始化的方式: //n为数组长度,an为

Java 数组学习笔记

数组的简单认识 简单理解java数组,就是可以创建并组装它们,通过使用整型索引值访问它们的元素,并且它们的尺寸不能改变,这里的它们就是数组. 数组的特殊性 在java中有很多方式去持有对象,那么数组的与众不同点在哪里? 数组与其他种类的容器区别有三个方面:效率.类型和保存基本类型的能力. 在java中,数组是一种效率最高的存储和随机访问对象引用序列的方式.数组就是一个简单的线性序列,这使得元素访问非常迅速.但是为之付出的代价就是数组对象的大小被固定,并且在其生命周期中不可改变. 在泛型之前,其他

12、sed、awk、数组 学习笔记

sed命令: sed 选项 "地址定界编辑命令" FILE ... 选项: -n 静默模式,不输出模式空间中的内容 -r 扩展的正则表达式 -f /path/to/script_file 指定sed脚本文件 -e 'script' -e 'script' 指定多个编辑指令 -i 直接编辑原文件 地址定界: startline,endline startline到endline之间的所有行 /pat1/,/pat2/ 第一次匹配pat1到第一次匹配pat2之间的所有行 /pattern/

JS数组学习笔记

最近在备课数组,发现很多ES5的方法平时很少用到.细节比较多,自己做了大量例子和整理,希望对大家了解JavaScript中的Array有所帮助. 概念 数组是值的有序集合.每个值叫做元素,每个元素在数组中都有数字位置编号,也就是索引.JS中的数组是弱类型的,数组中可以含有不同类型的元素.数组元素甚至可以是对象或其它数组. JS引擎一般会优化数组,按索引访问数组常常比访问一般对象属性明显迅速. 数组长度范围 from 0 to 4,294,967,295(2^23 - 1) 数组创建 var BA

java数组学习笔记

发现自己基础知识学的不够扎实,慢慢回顾下! 数组创建: 方式一:type[] 变量名 = new type[元素个数];  ——如:int[] a = new int[10]; 方式二:type 变量名[] = new type[元素个数];  ——如:int a[] = nwe int[10]; 方式三:type[] a= new type[]{初始化值,逗号分隔} ——如:int[] a=new int[]{1,2,3} 初始化时,不能同时定义维和初始化值  ——例如 :int[] a=ne