本文基于Coursera北大课程《数据结构基础》,所有文中非标注图片均来自课件,侵删
目录
1. 字符串基本概念
1.1 什么是字符串
1.2 字符编码
1.3 字符串数据类型
1.4 子串(substring)
2. 字符串的存储结构
3. 字符串运算的算法实现
4. 字符串的模式匹配(pattern matching)
4.1 朴素算法(Brute Force/Naive)
4.2 KMP快速模式匹配(Knuth-Morrit-Pratt)
4.2.1 字符串的特征向量定义
4.2.2 字符串的特征向量构造方法
参考资料
字符串是特殊的线性结构,即元素为字符的线性表。
设一个长度为N的字符串为S: "c0c1c2...cn-1",其中S为字符串串名,c0至cn-1则为串值,N为串长。
在编码上,字符编码使用了单字节(8 bits)的ASCII码对128个符号进行编码;在更复杂的文字例如中文、日语、韩语字符时,使用UNICODE(16 bits)进行编码。判断字符串的大小是通过编码顺序判断的,字符编码表一般遵循约定俗成的“偏序编码规则”。
根据语言不同而不同,总体来说有简单类型和复合类型两种观念。
子串就是从某个字符串中取出的一部分,而被取出的这个整体就是主串。
字符串存为链表没有什么很大的优势,因为其操作通常都是以串为单位进行的,所以字符串更多是顺序存储。
对于串长变化不大的字符串,有三种常见的处理方案:
Pascal是一个有影响的面向对象和面向过程编程语言,由尼克劳斯·维尔特在1968年9月设计,在1970年发行,作为一个小型的和高效的语言,意图鼓励使用结构化编程和数据结构进行良好的编程实践。
称作Object Pascal的一个派生是为面向对象编程设计的。
——摘自维基百科《Pascal(程式语言)》【1】
这里就是常规的一些算法的介绍,我觉得要注意的一点是字符串的复制,直接使用“=”是将地址复制给了对方,专门为对方开辟的地址就会消失。真正复制时是按字符挨个复制。
模式匹配就是在目标对象T中寻找一个给定的模式P的过程。例如在Linux中的grep,DNA信息的提取,确认是否具有某种结构等应用。
如下图所示,T是一个目标对象(字符串),P是一个模式(字符串)。用给定的模式P,在目标对象T中搜索与P完全相同的子串,并求出T中这样的第一个子串(简称“配串”),返回其首字符位置。
为了实现这个算法,下面介绍两种算法。
其本质是一个穷举法,尝试所有可能。但其中很多是不必要的,所以会造成冗余。
举一个课程中的例子,目标串T=aafgeefgeeast,模式串 P=fgeeas,用朴素模式匹配的方法共需要多少次比较?
首先比较P[0]和T[0], a和f不同,右移,直到T[2],从T[2]到T[5]都与P相同,但是T[6]和P[4](f和a)不同,所以继续右移,以此类推……
最后得到的答案是需要比较16次。
设T长度为n, P长度为m,则最坏情况要比较(n-m+1)次,整个算法最坏时间开销估计为O(m*n);最好的情况分为两种,第一种是找到了P,则是在前m个位置就找到了P,那么只需要O(m)的时间开销,第二种情况是没找到P,那么是O(n)。
快速匹配算法的核心思想就是尽量不要回溯,KMP就是一种无回溯的快速匹配算法。
一旦发生不匹配,我们直接将光标在T身上右移k个单位,而不是每次以一个单位向右移动。Knuth-Morrit-pratt发现,移动的k值只与P本身相关,与T无关。KMP的算法时间效率达到了O(m+n)。
设模式P由m个字符组成,记为:P=p0p1...pm-1
令特征向量N来表示P的字符分布特征,记为N=n0n1...nm-1。N在很多文献中也被称为next数组。
即寻找P第j个位置的特征数nj,使得首尾串k最长
举个课程中的例子,对于串S='abcdaabcab', 其特征向量N为:{-1, 0, 0, 0, 0, 1, 1, 2, 3, 1};优化的next数组为{-1, 0,0,0,-1,1,0,0,0,3,0}
字符串的特征向量这里很不好理解,下面附上一个我觉得讲的非常清楚的链接供参考,感谢作者
http://www.cnblogs.com/yahong/p/3420565.html
【1】https://zh.wikipedia.org/wiki/Pascal_(程式語言)