首页 > 其他分享 >后缀数组 SA

后缀数组 SA

时间:2023-10-16 20:35:39浏览次数:35  
标签:后缀 up 关键字 num 数组 排名 SA sa

膜拜 zxy,1h 学会 SA。这玩意真的好绕啊 >w<

给定一个字符串 \(S\),设 \(S(l,r)\) 表示 \(S_l\dots S_r\) 组成的字符串,\(s(i)\) 表示 \(S(i,n)\)。

将 \(s(1),\dots,s(n)\) 排序,设 \(sa[i]\) 表示排名为 \(i\) 的字符串为 \(s(sa[i])\)。

我们顺次考虑按照前 \(1,2,4,8,\dots,k\) 位 排好序的情况,那我们的问题是 how 倍增求解 qwq

我们知道 \(S(i,i+k-1)\) 和 \(S(i+k,i+2*k-1)\) 在长度为 \(k\) 下的排名,想要合并显然是先看前者再看后者即可,设前者为第一关键字,后者为第二关键字,一次合并 \(O(n)\),总的复杂度 \(O(n\log n)\)。

\(sa(i)\) 表示排名为 \(i\) 的字符串在原串中的起始位置。

\(x(i)\) 表示排名为 \(i\) 的第一关键字,\(y(i)\) 是排名为 \(i\) 的第二关键字。

n=strlen(s+1), m=122; // m 是字符种类数 
up(i,1,n) x[i]=s[i], c[x[i]]++; 
up(i,2,m) c[i]+=c[i-1];
up(i,1,n) sa[c[x[i]]--]=i; // 按 s(i,i) 缔造初始 SA  
for(int k=1; k<=n; k<<=1) { // 倍增长度 
	int num=0;
	up(i,n-k+1,n) y[++num]=i; // 这些位置的第二关键字为 null,是极小的,先对其进行赋值 o.O 
	up(i,1,n) if(sa[i]>k) y[++num]=sa[i]-k; // 以 sa[i] 作为第二关键字的情况 
	up(i,1,m) c[i]=0;  
	up(i,1,n) c[x[i]]++;
	up(i,2,m) c[i]+=c[i-1];
	down(i,n,1) sa[c[x[y[i]]]--]=y[i]; // 重构排名 SA,y 越大的排名越大 
	up(i,1,n) y[i]=x[i], x[i]=0; // from x to y ~ 
	num=1, x[sa[1]]=1; 
	up(i,2,n) {
		if(y[sa[i]]==y[sa[i-1]]&&y[sa[i]+k]==y[sa[i-1]+k]) x[sa[i]]=num;
		else x[sa[i]]=++num;
	} // 数一下排名相同的多少个
	if(num==n) break; m=num; // 更新种类数 
}
up(i,1,n) cout << sa[i] << ' '; // perfect!

标签:后缀,up,关键字,num,数组,排名,SA,sa
From: https://www.cnblogs.com/chelsyqwq/p/17768268.html

相关文章

  • 链表的头插和尾插(数组--链表)
    头插法代码示例publicclassLinkDemo{publicstaticvoidmain(String[]args){//将这个数组按头插的方式插入列表int[]arr={1,2,3,4,5,6,7,8,9};headIndert(arr);}publicstaticvoidheadIndert(int[]arr){Nodeli......
  • SAGA分布式
    Saga是由一系列的本地事务构成。每一个本地事务在更新完数据库之后,会发布一条消息或者一个事件来触发Saga中的下一个本地事务的执行。如果一个本地事务因为某些业务规则无法满足而失败,Saga会执行在这个失败的事务之前成功提交的所有事务的补偿操作。Saga的实现有很多种方式,其中最......
  • python学习之二位数组
    创建二维数组其实python没有数组的概念,是用list来代替的,创建其实可以直接写入行列式如下:也可以使用numpy,后面用到的话再写一篇运行结果如上从输入流写入数组目前只懂需要输入行跟列的二位数组,如果用到需要根据输入长度来判断的时候在补充 ......
  • 转载 | [AcSaveAsType -cad版本代号对应数字 ] & [AutoCAD的DWG文件格式版本代号列
    1. AcSaveAsType-cad版本代号对应数字 doc.SaveAs("D:\AutoCAD\1.dwg",61)#将当前文件另存为PyAutoCAD_SaveAs.dxf;#此时,程序关闭当前文件,将PyAutoCAD_SaveAs.dxf切换为当前文件。#61表示另存为文件的类型是AutoCAD2013DXF,常用类型如下:#12AutoCAD2000DWG(......
  • 创建numpy数组
     1.2.1创建NumPy数组的多种方式¶array:将数组转换为ndarray,推断dtype或者显示指定arange:类似内置函数range,返回ndarrayzeros:创建全0数组,可指定形状和dtypeones:创建全1数组,可指定形状和dtypeempty:创建新数组,只分配内存空间、不填充任何值1.2.2转换NumPy数......
  • 数据结构与算法 | 数组(Array)
    数组(Array)数组(Array)应该是最基础的数据结构之一,它由相同类型的元素组成的集合,并按照一定的顺序存储在内存中。每个元素都有一个唯一的索引,可以用于访问该元素。 //java数组示例 int[]numbers1={2,0,2,3,9,23}; //或者 int[]numbers2=newint[6];基本概念数组基......
  • SaaS模式相较传统CRM系统有何优势?
     SaaS模式的CRM客户管理系统相较于传统的CRM客户管理系统更加方便灵活,更加符合如今的市场环境。它解决了传统CRM系统投入大、维护难的难题,降低了中小企业导入CRM的门槛。下面详细说说SaaS模式相较传统CRM系统有何优势。 一、显著降低成本以前,企业部署一套CRM系统不仅要投入......
  • 数组有没有length()这个方法? String有没有length()这个方法?
    数组没有length()这个方法,有length的属性。String有有length()这个方法。 [1,2,3].lengh属性"123".length()方法......
  • postman 访问SAP odata 服务
    我们使用OData服务创建销售订单,这是一个HTTPpost请求,按照SAPC4C的规定需要在HTTP请求的头部附上一个CSRF token。为此我们先要使用一个独立的HTTPget请求去获取token: body区域里输入下面的json字符串:{“Name”:“JerryTest2018-12-26”,“TypeCode”:“2059”,“P......
  • Gym101064L The Knapsack problem
    CF传送门发现物品的体积很小,尝试从此处入手。设\(K\)为最大的物品体积。把背包体积\(m\)分成差不超过\(K\)的两部分,然后合并。这样需要求出\(f(\frac{m}{2}-K\sim\frac{m}{2}+K)\)。递归地,可以发现需要求出\(f(\frac{m}{2^k}-K\sim\frac{m}{2^k}+K)\)。最......