后缀数组--许智磊

合集下载

NOI国家集训队论文分类(至2008)(摘抄自C博客)

NOI国家集训队论文分类(至2008)(摘抄自C博客)

摘抄自C博客组合数学计数与统计2001 - 符文杰:《Pólya原理及其应用》2003 - 许智磊:《浅谈补集转化思想在统计问题中的应用》2007 - 周冬:《生成树的计数及其应用》2008 - 陈瑜希《Pólya计数法的应用》数位问题2009 - 高逸涵《数位计数问题解法研究》2009 - 刘聪《浅谈数位类统计问题》动态统计2004 - 薛矛:《解决动态统计问题的两把利刃》2007 - 余江伟:《如何解决动态统计问题》博弈2002 - 张一飞:《由感性认识到理性认识——透析一类搏弈游戏的解答过程》2007 - 王晓珂:《解析一类组合游戏》2009 - 曹钦翔《从“k倍动态减法游戏”出发探究一类组合游戏问题》2009 - 方展鹏《浅谈如何解决不平等博弈问题》2009 - 贾志豪《组合游戏略述——浅谈SG游戏的若干拓展及变形》母函数2009 - 毛杰明《母函数的性质及应用》拟阵2007 - 刘雨辰:《对拟阵的初步研究》线性规划2007 - 李宇骞:《浅谈信息学竞赛中的线性规划——简洁高效的单纯形法实现与应用》置换群2005 - 潘震皓:《置换群快速幂运算研究与探讨》问答交互2003 - 高正宇:《答案只有一个——浅谈问答式交互问题》猜数问题2003 - 张宁:《猜数问题的研究:<聪明的学生>一题的推广》2006 - 龙凡:《一类猜数问题的研究》数据结构数据结构2005 - 何林:《数据关系的简化》2006 - 朱晨光:《基本数据结构在信息学竞赛中的应用》2007 - 何森:《浅谈数据的合理组织》2008 - 曹钦翔《数据结构的提炼与压缩》结构联合2001 - 高寒蕊:《从圆桌问题谈数据结构的综合运用》2005 - 黄刚:《数据结构的联合》块状链表2005 - 蒋炎岩:《数据结构的联合——块状链表》2008 - 苏煜《对块状链表的一点研究》动态树2006 - 陈首元:《维护森林连通性——动态树》2007 - 袁昕颢:《动态树及其应用》左偏树2005 - 黄源河:《左偏树的特点及其应用》跳表2005 - 魏冉:《让算法的效率“跳起来”!——浅谈“跳跃表”的相关操作及其应用》2009 - 李骥扬《线段跳表——跳表的一个拓展》SBT2007 - 陈启峰:《Size Balance Tree》线段树2004 - 林涛:《线段树的应用》单调队列2006 - 汤泽:《浅析队列在一类单调性问题中的应用》哈希表2005 - 李羽修:《Hash函数的设计优化》2007 - 杨弋:《Hash在信息学竞赛中的一类应用》Splay2004 - 杨思雨:《伸展树的基本操作与应用》图论图论2005 - 任恺:《图论的基本思想及方法》模型建立2004 - 黄源河:《浅谈图论模型的建立与应用》2004 - 肖天:《“分层图思想”及其在信息学竞赛中的应用》网络流2001 - 江鹏:《从一道题目的解法试谈网络流的构造与算法》2002 - 金恺:《浅谈网络流算法的应用》2007 - 胡伯涛:《最小割模型在信息学竞赛中的应用》2007 - 王欣上:《浅谈基于分层思想的网络流算法》2008 - 周冬《两极相通——浅析最大—最小定理在信息学竞赛中的应用》最短路2006 - 余远铭:《最短路算法及其应用》2008 - 吕子鉷《浅谈最短径路问题中的分层思想》2009 - 姜碧野《SPFA算法的优化及应用》欧拉路2007 - 仇荣琦:《欧拉回路性质与应用探究》差分约束系统2006 - 冯威:《数与图的完美结合——浅析差分约束系统》平面图2003 - 刘才良:《平面图在信息学中的应用》2007 - 古楠:《平面嵌入》2-SAT2003 - 伍昱:《由对称性解2-SAT问题》最小生成树2004 - 吴景岳:《最小生成树算法及其应用》2004 - 汪汀:《最小生成树问题的拓展》二分图2005 - 王俊:《浅析二分图匹配在信息学竞赛中的应用》Voronoi图2006 - 王栋:《浅析平面Voronoi图的构造及应用》偶图2002 - 孙方成:《偶图的算法及应用》树树2002 - 周文超:《树结构在程序设计中的运用》2005 - 栗师:《树的乐园——一些与树有关的题目》路径问题2009 - 漆子超《分治算法在树的路径问题中的应用》最近公共祖先2007 - 郭华阳:《RMQ与LCA问题》划分问题2004 - 贝小辉:《浅析树的划分问题》数论欧几里得算法2009 - 金斌《欧几里得算法的应用》同余方程2003 - 姜尚仆:《模线性方程的应用——用数论方法解决整数问题》搜索搜索2001 - 骆骥:《由“汽车问题”浅谈深度搜索的一个方面——搜索对象与策略的重要性》2002 - 王知昆:《搜索顺序的选择》2005 - 汪汀:《参数搜索的应用》启发式2009 - 周而进《浅谈估价函数在信息学竞赛中的应用》优化2003 - 金恺:《探寻深度优先搜索中的优化技巧——从正方形剖分问题谈起》2003 - 刘一鸣:《一类搜索的优化思想——数据有序化》2006 - 黄晓愉:《深度优先搜索问题的优化技巧》背包问题2009 - 徐持衡《浅谈几类背包题》匹配2004 - 楼天城:《匹配算法在搜索问题中的巧用》概率概率2009 - 梅诗珂《信息学竞赛中概率问题求解初探》数学期望2009 - 汤可因《浅析竞赛中一类数学期望问题的解决方法》字符串字符串2003 - 周源:《浅析“最小表示法”思想在字符串循环同构问题中的应用》多串匹配2004 - 朱泽园:《多串匹配算法及其启示》2006 - 王赟:《Trie图的构建、活用与改进》2009 - 董华星《浅析字母树在信息学竞赛中的应用》后缀数组2004 - 许智磊:《后缀数组》2009 - 罗穗骞《后缀数组——处理字符串的有力工具》字符串匹配2003 - 饶向荣:《病毒的DNA———剖析一道字符匹配问题解析过程》2003 - 林希德:《求最大重复子串》动态规划动态规划2001 - 俞玮:《基本动态规划问题的扩展》2006 - 黄劲松:《贪婪的动态规划》2009 - 徐源盛《对一类动态规划问题的研究》状态压缩2008 - 陈丹琦《基于连通性状态压缩的动态规划问题》状态设计2008 - 刘弈《浅谈信息学中状态的合理设计与应用》树形DP2007 - 陈瑜希:《多角度思考创造性思维——运用树型动态规划解题的思路和方法探析》优化2001 - 毛子青:《动态规划算法的优化技巧》2003 - 项荣璟:《充分利用问题性质——例析动态规划的“个性化”优化》2004 - 朱晨光:《优化,再优化!——从《鹰蛋》一题浅析对动态规划算法的优化》2007 - 杨哲:《凸完全单调性的加强与应用》计算几何立体几何2003 - 陆可昱:《长方体体积并》2008 - 高亦陶《从立体几何问题看降低编程复杂度》计算几何思想2004 - 金恺:《极限法——解决几何最优化问题的捷径》2008 - 程芃祺《计算几何中的二分思想》2008 - 顾研《浅谈随机化思想在几何问题中的应用》圆2007 - 高逸涵:《与圆有关的离散化》半平面交2002 - 李澎煦:《半平面交的算法及其应用》2006 - 朱泽园:《半平面交的新算法及其实用价值》矩阵矩阵2008 - 俞华程《矩阵乘法在信息学中的应用》高斯消元2002 - 何江舟:《用高斯消元法解线性方程组》数学方法数学思想2002 - 何林:《猜想及其应用》2003 - 邵烜程:《数学思想助你一臂之力》数学归纳法2009 - 张昆玮《数学归纳法与解题之道》多项式2002 - 张家琳:《多项式乘法》数形结合2004 - 周源:《浅谈数形结合思想在信息学竞赛中的应用》黄金分割2005 - 杨思雨:《美,无处不在——浅谈“黄金分割”和信息学的联系》其他算法遗传算法2002 - 张宁:《遗传算法的特点及其应用》2005 - 钱自强:《关于遗传算法应用的分析与研究》信息论2003 - 侯启明:《信息论在信息学竞赛中的简单应用》染色与构造2002 - 杨旻旻:《构造法——解题的最短路径》2003 - 方奇:《染色法和构造法在棋盘上的应用》一类问题区间2008 - 周小博《浅谈信息学竞赛中的区间问题》序2005 - 龙凡:《序的应用》系2006 - 汪晔:《信息学中的参考系与坐标系》物理问题2008 - 方戈《浅析信息学竞赛中一类与物理有关的问题》编码与译码2008 - 周梦宇《码之道—浅谈信息学竞赛中的编码与译码问题》对策问题2002 - 骆骥:《浅析解“对策问题”的两种思路》优化算法优化2002 - 孙林春:《让我们做得更好——从解法谈程序优化》2004 - 胡伟栋:《减少冗余与算法优化》2005 - 杨弋:《从<小H的小屋>的解法谈算法的优化》2006 - 贾由:《由图论算法浅析算法优化》程序优化2006 - 周以苏:《论反汇编在时间常数优化中的应用》2009 - 骆可强《论程序底层优化的一些方法与技巧》语言C++2004 - 韩文弢:《论C++语言在信息学竞赛中的应用》策略策略2004 - 李锐喆:《细节——不可忽视的要素》2005 - 朱泽园:《回到起点——一种突破性思维》2006 - 陈启峰:《“约制、放宽”方法在解题中的应用》2006 - 李天翼:《从特殊情况考虑》2007 - 陈雪:《问题中的变与不变》2008 - 肖汉骏《例谈信息学竞赛分析中的“深”与“广”》倍增2005 - 朱晨光:《浅析倍增思想在信息学竞赛中的应用》二分2002 - 李睿:《二分法与统计问题》2002 - 许智磊:《二分,再二分!——从Mobiles(IOI2001)一题看多重二分》2005 - 杨俊:《二分策略在信息学竞赛中的应用》调整2006 - 唐文斌:《“调整”思想在信息学中的应用》随机化2007 - 刘家骅:《浅谈随机化在信息学竞赛中的应用》非完美算法2005 - 胡伟栋:《浅析非完美算法在信息学竞赛中的应用》2008 - 任一恒《非完美算法初探》提交答案题2003 - 雷环中:《结果提交类问题》守恒思想2004 - 何林:《信息学中守恒法的应用》极限法2003 - 王知昆:《浅谈用极大化思想解决最大子矩形问题》贪心2008 - 高逸涵《部分贪心思想在信息学竞赛中的应用》压缩法2005 - 周源:《压去冗余缩得精华——浅谈信息学竞赛中的“压缩法”》逆向思维2005 - 唐文斌:《正难则反——浅谈逆向思维在解题中的应用》穷举2004 - 鬲融:《浅谈特殊穷举思想的应用》目标转换2002 - 戴德承:《退一步海阔天空——“目标转化思想”的若干应用》2004 - 栗师:《转化目标在解题中的应用》类比2006 - 周戈林:《浅谈类比思想》分割与合并2006 - 俞鑫:《棋盘中的棋盘——浅谈棋盘的分割思想》2007 - 杨沐:《浅析信息学中的“分”与“合”》平衡思想2008 - 郑暾《平衡规划——浅析一类平衡思想的应用》。

(全国百强校)广东华南师范大学附属中学高中信息技术资料:处理字符串的有力工具-后缀数组

(全国百强校)广东华南师范大学附属中学高中信息技术资料:处理字符串的有力工具-后缀数组

f(n) = O(n) + f(2n/3) f(n) ≤ c×n + f(2n/3)
f(n)≤c×n+c×(2n/3)+c×(4n/9)+……≤3c×n 所以 f(n)=O(n)
由此看出,DC3算法是一个优秀的线性算法!
后缀数组的应用
例1:如果字符串L同时出现在字符串A
和字符串B中,则称字符串L是字符串A 和字符串B的公共子串。 给定两个字符串A和B,求最长公共子串。 例如:字符串“aaaba”和“abaa”的 最长公共子串为“aba”
DC3算法 复杂 难以实现
仅40行代码
DC3算法
(1)、先将后缀分成两部分,然后对 第一部分的后缀排序。
(2)、利用(1)的结果,对第二部分 的后缀排序。
(3)、将(1)和(2)的结果合并, 即完成对所有后缀排序。
(1)、将后缀分成两部分
字符的编号从0开始。 将后缀分成两部分: 第一部分是后缀k(k模3不等于0) 第二部分是后缀k(k模3等于0)
例1 最长公共子串
字符串的任何一个子串都是这个字符 串的某个后缀的前缀。求A和B的最长公 共子串等价于求A的后缀和B的后缀的最 长公共前缀的最大值。
将第二个字符串写在第一个字符串后 面,中间用一个没有出现过的字符隔开, 再求这个新的字符串的后缀数组。
如何高效的计算height数组?
如果按height[2],height[3],……, height[n]的顺序计算,最坏情况下时间复 杂度为O(n2)。这样做并没有利用字符串的 性质。定义h[i]=height[rank[i]],也就是 suffix(i)和在它前一名的后缀的最长公共前 缀。h数组有以下性质:

后缀数组

后缀数组

OI笔记]后缀数组学习笔记--后缀数组解题方法总结2010-04-15 07:37后缀数组是处理字符串的有力工具。

后缀数组是后缀树的一个非常精巧的替代品,它比后缀树容易编程实现,能够实现后缀树的很多功能而时间复杂度也并不逊色,而且它比后缀树所占用的内存空间小很多。

可以说,后缀数组比后缀树要更为实用。

自从拜读了罗穗骞大牛的WC2009论文《后缀数组——处理字符串的有力工具》后,经过若干星期的努力(中间有因某些原因而缓下来),终于把论文上面的练习题全部完成了,现在写写自己对后缀数组的理解和感悟。

在看本笔记时,请不要忘记了,这是笔记,而教材是《后缀数组——处理字符串的有力工具》。

一:后缀数组的实现1、定义:Suffix Array数组(SA数组)用于保存从小到大排好序之后的后缀。

RANK名次数组用来保存后缀S[i..n]在所有后缀中是第几小的后缀。

简单来说,SA数组表示的是“排第几的是谁”,RANK数组表示的是“你的排名是多少”。

2、求SA数组以及RANK数组的方法:详细的请转到罗穗骞大牛的论文,我的学习笔记重点不是要介绍这个。

3、对DA(倍增算法)的一些个人理解:由于我只学习了倍增算法,所以我只能谈谈我对它的理解。

DC3算法我没有去研究....DA算法我是根据罗穗骞的模板写的,根据自己的理解做了些许的小优化。

我们现在来看看罗穗骞大牛的模板:int wa[maxn],wb[maxn],wv[maxn],ws[maxn];int cmp(int *r,int a,int b,int l){return r[a]==r[b]&&r[a+l]==r[b+l];}void da(int *r,int *sa,int n,int m){int i,j,p,*x=wa,*y=wb,*t;for(i=0;i<m;i++) ws[i]=0;for(i=0;i<n;i++) ws[x[i]=r[i]]++;for(i=1;i<m;i++) ws[i]+=ws[i-1];for(i=n-1;i>=0;i--) sa[--ws[x[i]]]=i;for(j=1,p=1;p<n;j*=2,m=p){for(p=0,i=n-j;i<n;i++) y[p++]=i;for(i=0;i<n;i++) if(sa[i]>=j) y[p++]=sa[i]-j;for(i=0;i<n;i++) wv[i]=x[y[i]];for(i=0;i<m;i++) ws[i]=0;for(i=0;i<n;i++) ws[wv[i]]++;for(i=1;i<m;i++) ws[i]+=ws[i-1];for(i=n-1;i>=0;i--) sa[--ws[wv[i]]]=y[i];for(t=x,x=y,y=t,p=1,x[sa[0]]=0,i=1;i<n;i++)x[sa[i]]=cmp(y,sa[i-1],sa[i],j)?p-1:p++;}return;}其实,我个人认为,对于这个算法以及代码,无需过分深入地理解,只需记忆即可,理解只是为了帮助记忆罢了。

国家集训队2009论文集后缀数组——处理字符

国家集训队2009论文集后缀数组——处理字符

后缀数组 罗穗骞
例 10:长度不小于 k 的公共子串的个数(pku3415) ……………23 2.4 多个字符串的相关问题 …………………………………………………23
例 11:不小于 k 个字符串中的最长子串(pku3294) ……………………24 例 12:每个字符串至少出现两次且不重叠的最长子串(spoj220)……24 例 13:出现或反转后出现在每个字符串中的最长子串(pku3294)……24 三、结束语 …………………………………………………………………………25 参考文献 ……………………………………………………………………………25 致谢 …………………………………………………………………………………25
目录
后缀数组 罗穗骞
摘要 …………………………………………………………………………………4 关键字 ………………………………………………………………………………4 正文 …………………………………………………………………………………4 一、后缀数组的实现 …………………………………………………………………4
符 串 r 的 从 第 i 个 字 符 开 始 的 后 缀 表 示 为 Suffix(i) , 也 就 是 Suffix(i)=r[i..len(r)]。
大小比较:关于字符串的大小比较,是指通常所说的“字典顺序”比较,也 就是对于两个字符串 u、v,令 i 从 1 开始顺次比较 u[i]和 v[i],如果 u[i]=v[i]则令 i 加 1,否则若 u[i]<v[i]则认为 u<v,u[i]>v[i]则认为 u>v (也就是 v<u),比较结束。如果 i>len(u)或者 i>len(v)仍比较不出结果,那 么 若 len(u)<len(v) 则 认 为 u<v , 若 len(u)=len(v) 则 认 为 u=v , 若 len(u)>len(v)则 u>v。

后缀数组及其应用

后缀数组及其应用

其中l=2^k,且 l>=n
O(n)排序 。。。 。。。
2-rank[]
2-sa[]
8-rank[] 8-sa[] O(n)排序 4-rank[] 4-sa[] O(n)排序
算法最多进行logn次,每次 时间为O(N).所以最终时间 复杂度为O(nlogn)
倍增算法——思想总结
1、定义k-rank[],并利用k-rank[]求出2k-rank[],高 效的比较;充分利用了后缀之间的联系;
缺点: 该算法实现过于复杂,细节较多,且代码量较长,对于 一名信息竞赛的选手而言,在短短的5个小时内,要完全正 确地写出后缀树谈何容易。在各种各样的比赛中,我们要 选择实现相对简单,且效率较高的算法和数据结构。
随着广大OIERS的呼声,
后缀数组横空出世!!
*后缀数组 (Suffix Arrary)
后缀树的特点: 后缀树实质上是一棵字典树。从根节点到任意叶子节点 都对应了原串的一个后缀。但与Trie结构不同的是树上的每一 条边记录的不是单个字母,而是一个字符串。这样一来,将 空间从Trie的O(N^2)降到O(N) 。 同时,Trie的构造时间是O(N^2),而后缀树的构造时间仅 为O(N)。这也是后缀树广为人知的原因。 下面我们看个实例:
后缀数组的构造方法:
比较直观的想法——暴力排序: 把n个后缀预处理出来,快排,堆排,归并等,时 间复杂度O(nlogn),看上去还不错。 但仔细想想,两个字符串间比较有个strcmp(),这 明显不是线性。况且kmp也需要O(N+M)的时间,这样 一来时间复杂度接近O(n^2)。 当N>10000时就悲剧了。。。。。
通过上面的例子,通过k-rank[]可以在O(1)的时间内 完成suffix(i)和suffix(j)的比较。这样就充分利用了后缀之 间有机的联系。 具体实现当然不是枚举每两个串进行比较。进一步想 想,这样比较不就是将每个后缀看作一个元素,k-rank[i]作 为第一关键字,k-rank[i+k]作为第二关键字进行排序吗? 这时,排序方法又是一个大问题。虽然快排等比较型排序 可以做到O(nlogn),但是还不能满足后缀树组的高效要求。 每个元素只有两个关键字,而且关键字分布比较集中,相信聪 明的你已经想到了:

后缀数组——处理字符串的有力工具

后缀数组——处理字符串的有力工具
IOI2009 国家集训队论文
后缀数组 罗穗骞
信息学奥林匹克
China Nation Olympiad in Informatics
国家集训队论文
题 目: 后缀数组——处理字符串的有力工具
作 者:
罗穗骞
指导教师:
张学东
学 校:
华南师范大学附属中学
完成时间:
2009年1月
IOI2009 国家集训队论文
1.2倍增算法
倍增算法的主要思路是:用倍增的方法对每个字符开始的长度为 2k 的子字 符串进行排序,求出排名,即 rank 值。k 从 0 开始,每次加 1,当 2k 大于 n 以 后,每个字符开始的长度为 2k 的子字符串便相当于所有的后缀。并且这些子字 符串都一定已经比较出大小,即 rank 值中没有相同的值,那么此时的 rank 值就 是最后的结果。每一次排序都利用上次长度为 2k-1 的字符串的 rank 值,那么长 度为 2k 的字符串就可以用两个长度为 2k-1 的字符串的排名作为关键字表示,然 后进行基数排序,便得出了长度为 2k 的字符串的 rank 值。以字符串“aabaaaab” 为例,整个过程如图 2 所示。其中 x、y 是表示长度为 2k 的字符串的两个关键字 。
6
IOI2009 国家集训队论文
本页已使用福昕阅读器进行编辑。 福昕软件(C)2005-2009,版权所有, 仅供试用后。缀数组 罗穗骞
具体实现: int wa[maxn],wb[maxn],wv[maxn],ws[maxn]; int cmp(int *r,int a,int b,int l) {return r[a]==r[b]&&r[a+l]==r[b+l];} void da(int *r,int *sa,int n,int m) { int i,j,p,*x=wa,*y=wb,*t; for(i=0;i<m;i++) ws[i]=0; for(i=0;i<n;i++) ws[x[i]=r[i]]++; for(i=1;i<m;i++) ws[i]+=ws[i-1]; for(i=n-1;i>=0;i--) sa[--ws[x[i]]]=i; for(j=1,p=1;p<n;j*=2,m=p) { for(p=0,i=n-j;i<n;i++) y[p++]=i; for(i=0;i<n;i++) if(sa[i]>=j) y[p++]=sa[i]-j; for(i=0;i<n;i++) wv[i]=x[y[i]]; for(i=0;i<m;i++) ws[i]=0; for(i=0;i<n;i++) ws[wv[i]]++; for(i=1;i<m;i++) ws[i]+=ws[i-1]; for(i=n-1;i>=0;i--) sa[--ws[wv[i]]]=y[i]; for(t=x,x=y,y=t,p=1,x[sa[0]]=0,i=1;i<n;i++) x[sa[i]]=cmp(y,sa[i-1],sa[i],j)?p-1:p++; } return; }

2012年noi冬令营陈立杰讲稿(SAM后缀自动机)讲解

2012年noi冬令营陈立杰讲稿(SAM后缀自动机)讲解
后缀自动机 Suffix Automaton
杭州外国语学校 陈立杰 WJMZBMR
吐槽&回答
Q:你是哪里的弱菜?我听都没听说过! A:我是来自杭州外国语学校的陈立杰,确实是弱菜。 Q:Suffix Automaton?我根本就没有听说过这种数据结构。 A:这个还是有点用处的,等下我会讲的,你就当长知识
用的,所以trans(nq)就跟原来的trans(q)是一样的,拷贝即 可。
每个阶段
每个阶段
自此我们圆满的解决了转移的问题。 嘟嘟噜,搞完啦~~
每个阶段:回顾
每个阶段:回顾
否则新建节点nq,trans(nq,*)=trans(q,*)
Parent(nq) = Parent(q) (先前的) Parent(q) = nq Parent(np)=nq
了吧。
Q:呼噜噜~~~~~~
A:睡好。。。
先让我们看SPOJ上的一道题目
1812. Longest Common Substring II
题目大意:给出N(N <= 10)个长度不超过100000的字
符串,求他们的最长公共连续子串。
时限:SPOJ上的2s
一个简单的做法
二分答案之后使用哈希就可以在O(LlogL)的时间内解决这
对所有trans(v,x) == q的p的祖先v,trans(v,x) 改成nq
的区间中的叶子节点的Right集合的并集,那么我们也就可 以快速求出一个子串的所有出现位置了。
树的dfs序列:所有子树中节点组成一个区间。
线性构造算法
我们的构造算法是Online的,也就是从左到右逐个添加字
符串中的字符。依次构造SAM。
这个算法实现相比后缀树来说要简单很多,尽管可能不是

国家集训队2004论文集 许智磊

国家集训队2004论文集 许智磊

证。
设 Suffix(SA[i])=u,Suffix(SA[j])=v,Suffix(SA[k])=w。
由 u=LCP(i,j)v 得 u=pv;同理 v=pw。 于是 Suffix(SA[i])=pSuffix(SA[k]),即 LCP(i,k)≥p。 (1)
不难看出,这种做法是很笨拙的,因为它没有利用到各个后缀之间的有机 联系,所以它的效率不可能很高。即使采用字符串排序中比较高效的 Multi-key Quick Sort,最坏情况的时间复杂度仍然是 O(n2)的,不能满足我们的需要。
第 2 页 共 11 页
IOI2004 国家集训队论文 许智磊
下面介绍倍增算法(Doubling Algorithm),它正是充分利用了各个后缀之间的 联系,将构造后缀数组的最坏时间复杂度成功降至 O(nlogn)。
后 缀 数 组 后 缀 数 组 SA 是 一 个 一 维 数 组 , 它 保 存 1..n 的 某 个 排 列 SA[1],SA[2],...SA[n],并且保证 Suffix(SA[i])<Suffix(SA[i+1]),1≤i<n。也就是将 S 的 n 个后缀从小到大进行排序之后把排好序的后缀的开头位置顺次放入 SA 中。
出 SA2k 的复杂度就是 O(nlogn)。更聪明的方法是采用基数排序,复杂度为 O(n)。 求出 SA2k 之后就可以在 O(n)的时间内根据 SA2k 构造出 Rank2k。因此,从 SAk
和 Rankk 推出 SA2k 和 Rank2k 可以在 O(n)时间内完成。 下面只有一个问题需要解决:如何构造出 SA1 和 Rank1。这个问题非常简单:
IOI2004 国家集训队论文 许智磊
后缀数组
安徽省芜湖市第一中学 许智磊

基于程序框架Qt的嵌入式系统汉字库设计与实现

基于程序框架Qt的嵌入式系统汉字库设计与实现

基于程序框架Qt的嵌入式系统汉字库设计与实现殷知磊;张钟澍;肖跃先;薛松【摘要】在研究现有手持终端设备中文输入法及汉字库的基础上,提出了一种可以适合一般程序框架Qt的中文全拼输入法汉字库生成方法.使用该方法生成的汉字库结构合理,可以支持所有嵌入式Qt环境中的可显示汉字.经分析和实践验证,全拼输入法汉字库设计以及汉字库的生成方法非常适合ARM-Linux系统的全拼中文输入法使用.【期刊名称】《成都信息工程学院学报》【年(卷),期】2010(025)001【总页数】6页(P35-40)【关键词】实时软件工程;计算机应用技术;中文输入法;汉字库【作者】殷知磊;张钟澍;肖跃先;薛松【作者单位】成都信息工程学院计算机学院,四川,成都,610225;成都信息工程学院计算机学院,四川,成都,610225;成都信息工程学院计算机学院,四川,成都,610225;成都信息工程学院计算机学院,四川,成都,610225【正文语种】中文【中图分类】TP3911 引言1.1 研究背景目前ARM 板已经普遍应用于各种手机、玩具等电器产品,特别是嵌入式Linux技术与ARM的结合,以其开放的源代码、低廉的价格、方便的开发环境受到了许多开发厂家的青睐。

随着智能手持设备的快速发展,汉字的输入输出己经成为很多智能手持设备进行人机交互不可缺少的部分,其中以手机中汉字输入使用最为广泛。

目前已有的汉字库生成方法耗费人力物力较大、开发周期长、汉字采集不够完整、输入法对汉字库进行索引时速度较慢等问题;已有的汉字库的索引原理在输入法根据拼音索引汉字的时候需要大量的CPU时间,这显然不适合嵌入式设备的要求。

文中介绍的汉字库设计结构,可以在利用简单的设备,需要短时间内即可生成一个可以供中文全拼输入法使用的汉字库,特别适用于在项目周期短,又要求中文输入法支持的项目开发。

文中介绍的汉字库生成法属于支持中文全拼输入法的底层开发,为利用Qt/Embedded开发的输入法提供了汉字索引支持。

后缀树的设计与构造

后缀树的设计与构造

2019年第6期信息与电脑China Computer & Communication算法语言后缀树的设计与构造赵美勇 史昊臻 朱珍珍(山东科技大学,山东 济南 266590)摘 要:后缀树是处理字符串的一个优秀算法。

利用图像化设计可使后缀树更加清晰。

按照递推的思路,建立前i 个字符对应的后缀树,通过插入第i+1个字符的方式,建立前i+1个字符对应的后缀树。

由于字符串的任意子串都可以表示为某个后缀的前缀,因此可以设定当前节点为根节点。

父节点取子节点中贡献最大的节点,同时,记录其对应的字符串。

关键词:后缀树;数据结构;时间复杂度中图分类号:TP399 文献标识码:A 文章编号:1003-9767(2019)06-052-02Design and Construction of Suffix TreesZhao Meiyong, Shi Haozhen, Zhu Zhenzhen(Shandong University of Science and Technology, Jinan Shandong 266590, China)Abstract: Suffix tree is an excellent algorithm for string processing. The suffix tree can be clearer by image design. According tothe recursive thinking, the suffix tree corresponding to the first I characters is established, and the suffix tree corresponding to the first I + 1 characters is established by inserting the first I + 1 characters. Since any substring of a string can be represented as a prefix of a suffix, the current node can be set as the root node. The parent node takes the node that contributes the most to the child node, and records its corresponding string.Key words: suffix tree; data structure; time complexity0 引言字符串处理是计算机中很重要的问题,尤其在自然语言处理中。

国家集训队2004论文集_许智磊(后缀数组)

国家集训队2004论文集_许智磊(后缀数组)

第 1 页 共 11 页
IOI2004 国家集训队论文 许智磊
基本概念
首先明确一些必要的定义: 字符集 一个字符 集Σ是 一个建立了 全序关系的集合,也就是说 ,Σ 中 的任意两个不同的元素 α 和 β 都可以比较大小,要么 α<β,要么 β<α(也就是 α>β) 。字符集Σ中的元素称为字符。 字符串 一个字符串 S 是将 n 个字符顺次排列形成的数组,n 称为 S 的 长度,表示为 len(S)。S 的第 i 个字符表示为 S[i]。 子串 字符串 S 的子串 S[i..j],i≤j,表示 S 串中从 i 到 j 这一段,也就 是顺次排列 S[i],S[i+1],...,S[j]形成的字符串。 后缀 后缀是指从某个位置 i 开始到整个串末尾结束的一个特殊子串。 字符串 S 的从 i 开头的后缀表示为 Suffix(S,i),也就是 Suffix(S,i)=S[i..len(S)]。 关于字符串的 大小比较,是 指通常所说 的“字 典顺序 ”比较 ,也就是对 于 两个字符串 u、v,令 i 从 1 开始顺次比较 u[i]和 v[i],如果 u[i]=v[i]则令 i 加 1, 否则若 u[i]<v[i]则认为 u<v,u[i]>v[i]则认为 u>v(也就是 v<u) ,比较结束。如 果 i>len(u) 或 者 i>len(v) 仍 比较 出 结 果 , 那么若 len(u)<len(v) 则 认为 u<v , 若 len(u)=len(v)则认为 u=v,若 len(u)>len(v)则 u>v。 从字符串的大小比较的定义来看,S 的两个开头位置不同的后缀 u 和 v 进行 比较的结果不可能是相等,因为 u=v 的必要条件 len(u)=len(v)在这里不可能满 足。 下面我们约定一个字符集Σ和一个字符串 S,设 len(S)=n,且 S[n]='$',也 就是说 S 以一个特殊字符'$'结尾,并且'$'小于Σ中的任何一个字符。除了 S[n] 之外,S 中的其他字符都属于Σ。对于约定的字符串 S,从位置 i 开头的后缀直 接写成 Suffix(i),省去参数 S。 后 缀 数 组 后 缀 数 组 SA 是 一 个 一 维 数 组 , 它 保 存 1..n 的 某 个 排 列 SA[1],SA[2],...SA[n] ,并 且 保证 Suffix(SA[i])<Suffix(SA[i+1]),1≤i<n。 也就是 将 S 的 n 个后缀从小到大进行排序之后把排好序的后缀的开头位置顺次放入 SA 中。 名次数组 名次数组 Rank=SA-1,也就是说若 SA[i]=j,则 Rank[j]=i,不难 看出 Rank[i]保存的是 Suffix(i)在所有后缀中从小到大排列的“名次” 。

后缀数组——处理字符串的有力工具

后缀数组——处理字符串的有力工具

后缀数组 罗穗骞
例 10:长度不小于 k 的公共子串的个数(pku3415) ……………23 2.4 多个字符串的相关问题 …………………………………………………23
例 11:不小 于 k 个字符串中的最长子串(pku3294) ……………………24 例 12:每个字符串至少出现两次且不重叠的最长子串(spoj220)……24 例 13:出现或反转后出现在每个字符串中的最长子串(pku3294)……24 三、结束语 …………………………………………………………………………25 3.1 总结 ………………………………………………………………………25 3.2 参考文献 …………………………………………………………………25 3.3 致谢 ………………………………………………………………………25
1.2倍增算法
对每个字符开始的长度为 2k 的子字符串进行排序,求出排名,即 rank 值 。k 从 0 开始,每次加 1,当 2k 大于 n 以后,每个字符开始的长度为 2k 的子字符串 便相当于所有的后缀。并且这些子字符串都一定已经比较出大小,即 rank 值中 没有相同的值,那么此时的 rank 值就是最后的结果。每一次排序都利用上次长 度为 2k-1 的字符串的 rank 值,那么长度为 2k 的字符串就可以用两个长度为 2k-1 的字符串的排名作为关键字表示,然后进行基数排序,便得出了长度为 2k 的字 符串的 rank 值。以字符串“aabaaaab”为例,整个过程如图 2 所示。其中 x、y 是表示长度为 2k 的字符串的两个关键字。
例 1:最长公共前缀 ……………………………………………………17 2.2 单个字符串的相关问题 …………………………………………………17
2.2.1 重复子串 ………………………………………………………17 例 2:可重叠最长重复子串 ………………………………………17 例 3:不可重叠最长重复子串(pku1743)…………………………18 例 4:可重叠的最长重复子串(pku3261)…………………………19

交通信号控制中的延误计算与分析

交通信号控制中的延误计算与分析

是通行能力、饱和度、停车次数、车辆受阻延误时间, 同时它们也
是作为交叉口信号配时设计的基础。信号设计的目标就是寻求
最大的通行能力, 最低的饱和度, 并且使得通过交叉口的全部车
辆总延误时间最短或停车次数最少。当然, 除了这四个基本的动
态特性的参数外还有其它的次级参数, 比如车辆在交叉口的燃
油 消 耗 量 、废 气 排 放 量 以 及 运 营 成 本 。本 篇 文 章 主 要 讨 论 的 是 其
从上面的分析看延误计算与周期、饱和度等都有关系, 只有
真正了解了的延误计算相关参数的影响才能准确的计算出车辆 的延误时间。延误计算结果将被用于信号优化配时, 更说明了准 确计算的必要性。
参考文献: 1. 荆便顺.道路交通控制工程[ M] .北京: 人民交通出版社, 1995.119 ̄131. 2. 全永燊.城市交通控制[ M] .北京: 人民交通出版社, 1989.11 ̄95. 3. 尹宏宾 徐建闽.道 路 交 通 控 制 技 术 [ M] .广 州 : 华 南 理 工 大 学 出 版 社 , 2000,4.12 ̄64. 4. 黄辉先. 城市交通信号优化控制方法的研究: [ 博士学位论文] [ D] .西 安: 西北工业大学控制理论与控制专业, 2000.26 ̄31. 5. 徐吉万..城市交通的计算机控制和管理[M ].北京: 测绘出版社,, 1988. 6. 吴瑞麟, 沈建武.城市道路设计[ M] .北京: 人民交通出版社, 2003.110 ̄ 127. 7. 杨佩昆, 吴兵.交通管理与控制[ M] .北京: 人民交通出版社, 2003,2.79 ̄ 144. 8. 杨晓光等.城市道路交通设计指南[ M] .北京: 人民交通出版社, 2003,6. 120 ̄158. 9. 徐吉谦.交通工程总论.[ M] .北京: 人民交通出版社.1989,6.51 ̄92.

详细解析后缀数组(RMQ及LCP)

详细解析后缀数组(RMQ及LCP)
询问数组height中下标从 i+1 到 j 范围内所有元素的最小值
经典的RMQ (Range Minimum Query)问题!!!
➢线段树、排序树 —— O(nlogn)预处理 , O(logn)每次询问 ➢标准RMQ方法 —— O(n)预处理 , O(1)每次询问
后缀数组——辅助工具
采用一种“神奇的”方法,可以在O(n)时间内计算出height数组 采用标准RMQ方法在O(n)时间内进行预处理 之后就可以在常数时间内算出任何的LCP(i,j)
名次数组
后缀数组——构造方法
如何构造后缀数组?
把n个后缀当作n个字符串,按照普通的方法进行排序 —— O(n2)
低效的原因 —— 把后缀仅仅当作普通的、独立 的字符串,忽略了后缀之间存在的有机联系。
后缀数组——构造方法
u[1..k] ,len(u)≥k 对字符串u,定义uk =
u
,len(u)<k
LCP Theorem 对任何1≤i<j≤n LCP(i,j)=min{LCP(k-1,k) | i+1≤k≤j} 称j-i为LCP(i,j)的“跨度”,LCP Theorem意义为: 跨度大于1的LCP值可以表示成一段跨度等于1的LCP值的最小值
后缀数组——辅助工具
LCP(i,j)=3
4=LCP(i,i+1)
后缀是一种特殊的子串 从某个位置i开始到整个串的末尾结束 S的从i开头的后缀等价于S[i..len(S)]
后缀数组——定义和符号
约定一个字符集Σ 待处理的字符串约定为S,约定len(S)=n 规定S以字符“$”结尾,即S[n]=“$”
“$”小于Σ中所有的字符 除了S[n]=“$”之外,S的其他字符都属于Σ

poj2406PowerStrings后缀数组解法

poj2406PowerStrings后缀数组解法

poj2406PowerStrings后缀数组解法连续重复⼦串问题poj 2406 Power Strings问⼀个串能否写成a^n次⽅这种形式。

虽然这题⽤kmp做⽐较合适,但是我们还是⽤后缀数组做⼀做,巩固后缀数组的能⼒。

对于⼀个串,如果能写出a^n这种形式,我们可以暴⼒枚举循环节长度L,那么后缀suffix(1)和suffix(1 + L)的LCP应该就是 lenstr - L。

如果能满⾜,那就是,不能,就不是。

这题的话da算法还是超时,等我学了DC3再写上来。

其实这题可以不⽤枚举,考虑到如果能写成a^n这种形式,那么其循环节长度必定为 lenstr - height[rank[1]]给个图可能会更清楚如果是循环节,那么height[rank[1]]就是第1位的排名前后的lcp,肯定是第⼆个循环节那⾥的。

然后暴⼒判断⼀下就⾏~dc3, 2750ms才能卡过去#include <cstdio>#include <cstdlib>#include <cstring>#include <cmath>#include <algorithm>using namespace std;#define inf (0x3f3f3f3f)typedef long long int LL;#include <iostream>#include <sstream>#include <vector>#include <set>#include <map>#include <queue>#include <string>const int maxn = 3 * 1000000 + 20;const int N = maxn;#define F(x) ((x)/3+((x)%3==1?0:tb))#define G(x) ((x)<tb?(x)*3+1:((x)-tb)*3+2)int r[maxn];int wa[maxn],wb[maxn],wv[maxn],WS[maxn];int sa[maxn];int c0(int *r,int a,int b) {return r[a]==r[b]&&r[a+1]==r[b+1]&&r[a+2]==r[b+2];}int c12(int k,int *r,int a,int b) {if(k==2) return r[a]<r[b]||r[a]==r[b]&&c12(1,r,a+1,b+1);else return r[a]<r[b]||r[a]==r[b]&&wv[a+1]<wv[b+1];}void sort(int *r,int *a,int *b,int n,int m) {int i;for(i=0; i<n; i++) wv[i]=r[a[i]];for(i=0; i<m; i++) WS[i]=0;for(i=0; i<n; i++) WS[wv[i]]++;for(i=1; i<m; i++) WS[i]+=WS[i-1];for(i=n-1; i>=0; i--) b[--WS[wv[i]]]=a[i];return;}void dc3(int *r,int *sa,int n,int m) { //涵义与DA 相同int i,j,*rn=r+n,*san=sa+n,ta=0,tb=(n+1)/3,tbc=0,p;r[n]=r[n+1]=0;for(i=0; i<n; i++) if(i%3!=0) wa[tbc++]=i;sort(r+2,wa,wb,tbc,m);sort(r+1,wb,wa,tbc,m);sort(r,wa,wb,tbc,m);for(p=1,rn[F(wb[0])]=0,i=1; i<tbc; i++)rn[F(wb[i])]=c0(r,wb[i-1],wb[i])?p-1:p++;if(p<tbc) dc3(rn,san,tbc,p);else for(i=0; i<tbc; i++) san[rn[i]]=i;for(i=0; i<tbc; i++) if(san[i]<tb) wb[ta++]=san[i]*3;if(n%3==1) wb[ta++]=n-1;sort(r,wb,wa,ta,m);for(i=0; i<tbc; i++) wv[wb[i]=G(san[i])]=i;for(i=0,j=0,p=0; i<ta && j<tbc; p++)sa[p]=c12(wb[j]%3,r,wa[i],wb[j])?wa[i++]:wb[j++];for(; i<ta; p++) sa[p]=wa[i++];for(; j<tbc; p++) sa[p]=wb[j++];return;}int rank[maxn], height[maxn];void calheight(int *r,int *sa,int n) { // 此处N为实际长度int i,j,k=0; // height[]的合法范围为 1-N, 其中0是结尾加⼊的字符for(i=1; i<=n; i++) rank[sa[i]]=i; // 根据SA求RANKfor(i=0; i<n; height[rank[i++]] = k ) // 定义:h[i] = height[ rank[i] ]for(k?k--:0,j=sa[rank[i]-1]; r[i+k]==r[j+k]; k++); //根据 h[i] >= h[i-1]-1 来优化计算height过程}char str[maxn];void work() {int lenstr = strlen(str);for (int i = 0; i < lenstr; ++i) r[i] = str[i];r[lenstr] = 0;dc3(r, sa, lenstr + 1, 128);calheight(r, sa, lenstr);int t = lenstr - height[rank[0]];if (t == lenstr || lenstr % t != 0) {printf("1\n");} else {for (int i = t; i < lenstr; i += t) {for (int j = 0; j < t; ++j) {if (str[j] != str[i + j]) {printf("1\n");return;}}}printf("%d\n", lenstr / t);}}int main() {#ifdef localfreopen("data.txt","r",stdin);#endifwhile (scanf("%s", str) != EOF) {if (str[0] == '.') break;work();}return0;}View Code。

中缀及后缀算术表达式在运算中的应用研究

中缀及后缀算术表达式在运算中的应用研究

Computer Knowledge and Technology 电脑知识与技术第5卷第32期(2009年11月)软件设计开发本栏目责任编辑:谢媛媛中缀及后缀算术表达式在运算中的应用研究郭萌萌,许永昌(山东英才学院,山东济南250104)摘要:表达式求值是程序设计语言编译中的一个最基本问题。

与人们习惯的中缀表示的表达式相比,后缀表达式不存在括号,没有优先级的差别,表达式中各个运算是按照运算符出现的顺序进行的。

因此非常适合串行工作的计算机处理方式。

该文首先对这两种表达式表示方法进行了分析比较,然后通过具体分析实现这两种表达式求值的算法来论证表达式后缀表示优于中缀表示。

最后简要谈一下中缀表达式到后缀表达式的转换。

关键词:中缀表达式;后缀表达式;算符优先;堆栈中图分类号:TP31文献标识码:A 文章编号:1009-3044(2009)32-8921-03A Study of Index and Suffix Arithmetic Expression in the Operation Applied ResearchGUO Meng-meng,XU Yong-chang(Shandong Yingcai College,Jinan 250104,China)Abstract:The expression evaluation is the most basic question in programming language pared with infix expression with which people are familiar,suffix expression does not have the parenthesis,nor does it have the priority difference;each operation is carried out according to the order in which the operator appears.Therefore it is suitable for the serial work of the computer processing mode.This article first analyses and compares these two kinds of expression,then attempts to prove that suffix expression is superior to infix expression through the concrete analysis of the realization of evaluation algorithm of these two kinds of expression.Finally it discusses briefly the trans -formation of infix expression into the suffix expression.Key words:infix expression;suffix expression;priority operator;stack表达式求值是程序设计语言编译中的一个最基本问题。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

后缀数组——应用举例
回文串——顺读和倒读完全一样的字符串 奇回文串 字符串u满足:
1. len(u)=p为奇数
回文串
2. 对任何1≤i≤(p-1)/2,u[i]=u[p-i+1]
偶回文串 字符串v满足:
1. len(v)=q为奇数 2. 对任何1≤i≤q/2,v[i]=v[q-i+1]
后缀数组——应用举例
后缀数组
芜湖一中 许智磊
后缀数组——字符串处理中的有力武器 后缀树的一个简单而高效的替代品
当今字符串处理研究中的热门
让我们一同揭开她神秘的面纱
后缀数组——定义和符号
字符集、字符、字符串都按照惯常的定义 字符串S的长度表示为len(S) 字符串的下标从1开始到len(S)结束 字符串S的第i个字符表示为S[i] 从i到j这一段的子串表示为S[i..j] 后缀是一种特殊的子串
= O(nlogn)
后缀数组 VS 后缀树
后缀树也可以做到类似的事情
后缀数组有什么优势呢?
后缀数组 VS 后缀树
后缀数组在信息学竞赛中最大的优势:
易于理解,易于编程,易于调试
后缀数组比后缀树占用的空间少
——处理长字符串,如DNA分析
后缀数组 VS 后缀树
时间复杂度的比较
按照字符总数|Σ|把字符集Σ分为三种类型: Constant Alphabet Integer Alphabet General Alphabet Constant Alphabet —— |Σ|是一个常数 —— |Σ|和字符串长度n规模相当 —— 对|Σ|没有任何限制 Integer Alphabet General Alphabet
跨度大于1的LCP值可以表示成一段跨度等于1的LCP值的最小值
后缀数组——辅助工具
Suffix(SA[i])
4=LCP(i,i+1)
Suffix(SA[i+1]) LCP(i,j)=3
3=LCP(i+1,i+2)
Suffix(SA[i+2]) 5=LCP(i+2,j) Suffix(SA[j])
后缀数组——辅助工具
对两个字符串u,v,
u<kv 当且仅当 uk<vk u=kv 当且仅当 uk=vk u≤kv 当且仅当 uk≤vk
后缀数组——构造方法
k k k k
j+k 设u=Suffix(i),v=Suffix(j) 后缀u,以i开头 后缀v,以i开头
i+k
比较红色字符相当于在k-前缀意义下比较 在2k-前缀意义下比较两个后缀可以转化成 和 Suffix(j) 对u、Suffix(i) v在2k-前缀意义下进行比较
后缀数组 VS 后缀树
结论 后缀数组是直接针对General Alphabet设计的算法
对于Integer和General以及|Σ|较大的Constant Alphabet,后 复杂度跟字符集的类型没有关系 缀树甚至在时间复杂度上都无法胜过后缀数组。 后缀树则对不同字符集有不同的表现 但是对于|Σ|较小的Constant Alphabet, 如果采用儿子-兄弟方式来表达后缀树: 后缀树还是有着速度上的优势的。 构造的复杂度为 O(n* |Σ|) 解决方法:每个节点建立一棵 红黑 树来保存儿子,复杂 度为O(n*log |Σ|)。 ——显然不适合 Integer和General Alphabet, ——我们要根据实际情况,因“题”制宜选择合适 ——竞赛的时候有时间编吗? 对于|Σ|稍大的Constant Alphabet也无法胜任
Suffix(i)
后缀数组——定义和符号
字符串的大小关系 按照通常所说的“字典顺序”进行比 较 我们对S的n个后缀按照字典顺序从小到大排序
将排序后的后缀的开头位置顺次放入数组SA中,称为
后缀数组
令Rank[i]保存Suffix(i)在排序中的名次,称数组Rank为
名次数组
后缀数组——构造方法
如何构造后缀数组?
从某个位置i开始到整个串的末尾结束
S的从i开头的后缀等价于S[i..len(S)]
后缀数组——定义和符号
约定一个字符集Σ
待处理的字符串约定为S,约定len(S)=n
规定S以字符“$”结尾,即S[n]=“$” “$”小于Σ中所有的字符 除了S[n]=“$”之外,S的其他字符都属于Σ 对于约定的字符串S,其i开头的后缀表示为
倍 增 思 想
参与比较的前缀长度达到n以上时结束
后缀数组——辅助工具
仅仅靠后缀数组和名次数组
有时候还不能很好地处理问题
后缀数组的最佳搭档——LCP
定义两个字符串的最长公共前缀Longest Common Prefix
lcp(u,v)=max{i|u=iv} 也就是从头开始比较u和v的对应字符持续相等的最远值
采用基数排序O(n)
可以在O(n)时间内由Rankk求出SA2k 也就可以在O(n)时间内求出Rank2k
后缀数组——构造方法
1-前缀比较关系实际上是对字符串的第一个字符进行比较 可以直接根据开头字符对所有后缀进行排序求出SA1
采用快速排序,复杂度为O(nlogn)
然后根据SA1在O(n)时间内求出Rank1
把n个后缀当作n个字符串,按照普通的方法进行排序 —— O(n2) 低效的原因 —— 把后缀仅仅当作普通的、独立
的字符串,忽略了后缀之间存在的有机联系。
后缀数组——构造方法
对字符串u,定义uk = u[1..k] ,len(u)≥k
u
k k
,len(u)<k
k
倍增算法 (Doubling Algorithm) 定义k-前缀比较关系< ,= 和≤
k-名次数组
后缀数组——构造方法
利用SAk可以在O(n)时间内求出Rankk
利用Rankk可以在常数时间内对两个 后缀进行k-前缀意义下的大小比较
后缀数组——构造方法
如果已经求出Rankk 可以在常数时间内对两个后缀进行k-前缀意义下的比较 可以在常数时间内对两个后缀进行2k-前缀意义下的比较
可以很方便地对所有的后缀在2k-前缀意义下排序 采用快速排序O(nlogn)
后缀数组——辅助工具
采用一种“神奇的”方法,可以在O(n)时间内计算出height数组 采用标准RMQ方法在O(n)时间内进行预处理 之后就可以在常数时间内算出任何的LCP(i,j)
可以在常数时间内计算出
这是后缀数组
最常用以及最强大的功能之一 任何两个后缀的最长公共前缀
后缀数组——应用举例
怎样使用后缀数组?
的数据结构
后缀数组——最后的话
研究后缀数组,不是因为害怕后缀树的繁琐 也没有贬低后缀树,抬高后缀数组的意思 对于功能相似的两个数据结构,我们应 该灵活地掌握,有比较有选择地使用
构造后缀数组用到的倍增思想对我们的思考也是有帮助的
后缀数组
字符串T的回文子串——T的子串,并且是回文串 字符串T的最长回文回文子串
给出最大长度即可
后缀数组——应用举例
分析求最长奇回文子串的算法
最长偶回文子串可以类似求出
后缀数组——应用举例
枚举奇回文串中间一个字符的位置 尽量向两边扩展
后缀数组——应用举例
后缀数组——辅助工具
定义LCP(i,j)=lcp(Suffix(SA[i]),Suffix(SA[j])) 也就是SA数组中第i个和第j个后缀的最长公共前缀 LCP Theorem 对任何1≤i<j≤n LCP(i,j)=min{LCP(k-1,k) | i+1≤k≤j} 称j-i为LCP(i,j)的“跨度”,LCP Theorem意义为:
可以在O(nlogn)时间内求出SA1和Rank1
后缀数组——构造方法
直接根 据首字 符排序 SA1 O(nlogn) Rank1 O(n) SA2 SA4 O(n)
Rank2
Rank4
O(n)
m=2t且m≥n
SAm Rankm
O(n)
……
O(n)
SA8 Rank8
O(nlogn)的操作一次
总复杂度为
O(n)的操作[logn]次
O(nlogn)
后缀数组——构造方法
m≥n,
SAm=SA
Rankm=Rank
我们已经在O(nlogn)的时间内构造出了
后缀数组SA 和 名次数组Rank
后缀数组——方法总结
利用到后缀之间的联系
用k-前缀比较关系来表达2k-前缀比较关系
每次可以将参与比较的前缀长度加倍
根据SAk、Rankk求出SA2k、Rank2k
求以i为中心向两边扩展的最远值,等价于 求Suffix(i) 和Suffix(i') 的最长公共前缀 同时和粉红串 反射相等 Suffix(i) 和Suffix(i') 的公共前缀
后缀数组!!!
后缀数组——应用举例
解法: 1. 初始化答案为0。按照前述方法修改串T,得到串S 2. 求出后缀数组SA、名次数组Rank 3. 计算height数组并进行标准RMQ方法预处理 4. 枚举i,计算以i为对称中心的极长回文串并更新答案 复杂度: O(n) + O(nlogn) + 2*O(n) + n*O(1)
设height[i]=LCP(i-1,i)
根据LCP Theorem
LCP(i,j)=min{height[k] | i+1≤k≤j} 计算LCP(i,j)等价于 询问数组height中下标从 i+1 到 j 范围内所有元素的最小值
经典的RMQ (Range Minimum Query)问题!!!
线段树、排序树 —— O(nlogn)预处理 , O(logn)每次询问 标准RMQ方法 —— O(n)预处理 , O(1)每次询问
相关文档
最新文档