一、简介
串(string):字符串简称串,是由零个或多个字符组成的有限序列,使用单引号括起来,例如 s='abc'。
空串:由零个字符组成。
子串:串中任意个连续的字符组成的子序列成为该串的子串。
串的函数:1.求子串SubString函数。2、字符串复制 StrCpy函数 ....................
二、串的表示和实现
2/1定长顺序存储表示
类似于线性表,使用一组地址连续存储单元存储串值得字符序列。
2/2堆分配存储方式
存储特点:仍然以一组地址连续的存储单元存放串值字符序列,单他们存储空间是在执行程序过程中动态分配。
2/3 串的块链存储表示
和线性表的链式存储结构一样,也可以采用链表方式存储串值,每个结点可以存放一个字符或多个字符。
三、串算法
(一)模式匹配算法
子串的定位操作称为串的模式匹配。
BF算法:分别利用指数指针i和j指示主串S和模式串T中当前正待比较的字符的位置。从主串S的pos个字符起和模式的第一个字符进行比较,若相等,则继续逐个比较后续字符,否则从主串的下一个字符起重新再和模式的字符进行比较。过在这个过程中,i与j都需要回溯。时间复查度为O(n+m),其中n和m为主串和模式的长度。
例如
第一趟:i=3,j=3,若匹配,则i++,j++。不匹配,则i回溯到2,j回溯到1。
第二趟:i=2,j=1, 若匹配,则i++,j++。不匹配,i=3, j回溯到1。
。。。。
改进的方法:KMP算法。每当一趟匹配过程中出现不等时,不需回溯i指针,而是利用已经得到的“部分匹配”的结果将模式向右尽可能的远的距离后,继续比较。
KMP算法的核心:i不必回溯,j避免不必要的回溯,什么是不必要的回溯,问题的关键在与模式串,与主串无关。即j回溯到的位置与模式串自身有关,即需要求next数组对应的值。如下图next数组的值,即为当j的位置与主串匹配不上时,j回溯的位置为next[j]的值。
next数组的手动求值?手动求值的方法很多,这只是其中的一种方法。在考试中,经常会出现求next值的题目。
例如:
j=1时,next[1]=0,固定。
j=2时,next[2]=1,固定。
j=3时,next[3]=1,计算j=3前面的字符串前后缀(不包含字符本身)最大相似长度+1,例如ab ,前缀a,后缀b,相识长度0,0+1=1.
j=4时,next[4]=2,计算j=4前面的字符串前后缀(不包含字符本身)最大相似长度+1,例如aba,前缀a,ab,后缀a,ba,最大相识长度为1,1+1=2。
j=5时,next[5]=2,计算j=4前面的字符串前后缀(不包含字符本身)最大相似长度+1,例如abaa,前缀a,ab,aba,后缀,a,aa,baa,,最大相识长度为1,1+1=2。
j=6时,next[6]=3,计算j=4前面的字符串前后缀(不包含字符本身)最大相似长度+1,例如abaab,前缀a,ab,aba,abaa,后缀b,ab,aab,baab。前缀ab与后缀ab相识并且为长度为2,故2+1=3。
依次类推。。。。。
在某些情况下,next的值依然还存在一定缺点,即回溯的位置相对于采用nextval值比较的次数更多。可以采用继续优化得到nextval数组的值比较,提升模式匹配算法过程中的效率。
序号 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 |
模式串 | a | b | a | a | b | c | a | c |
next[] | 0 | 1 | 1 | 2 | 2 | 3 | 1 | 2 |
nextval[] | 0 | 1 | 0 | 2 | 1 | 3 | 0 | 2 |
如何求nextval的值?大部分情况,用当前字符与next值对应字符比较,相同,取0,不同取当前next值。其它,关注第五位。
第一位nextval的值必定为0,
第二位:第二位如果于第一位相同则取相同值下的next值为0,如果不同则取当下next的值为1。
第三位:第三位a与第一位a比较,相同则为0。
第四位:第四位a与第二位b比较,不同取当前的next值,为2。
第五位:第五位b与第二位b进行比较,相同,继续拿第二位与第一位比较,不同,则第五位的nextval值为第二位的next值,为1。
第六位:第六位c与第三位a比较,不同,取当前next值,为3.
第七位:第七位a与第一位a比较,相同,取0。
第八位:第八位c与第二位b比较,不同取当前next值为2.
代码求值
注:模式字符串T[0]存储字符串的长度,若需模式串“abcd”需要比较字符串的长度为4,则T[0]=5。初始化next[0]=0,第一趟next[1]=1。
代码直接求nextval求值。
KMP算法