串名、串值、串长、空串、空格串。
字符串的比较
字符串模式匹配算法:
1. 简单字符串模式匹配算法
最简单实现是用字符串P的字符依次与字符串T中的字符进行比较。实现思想是,首先将子串P从第0个字符起与主串T的第pos个字符起依次比较对应字符,如全部对应相等,则表明已找到匹配,成功终止。否则将子串P从第0个子串起与主串T的第pos+1个字符起依次比较字符。如此进行,直到某次成功匹配。或某次T中无足够的剩余字符与P中个字符匹配失败为止。
2. 首尾字符串模式匹配算法
为了避免在每趟匹配的最后一个字符时才发现不能匹配,可采用从模式串的两头分别比较的方法,先比较模式串的第0个字符,再比较模式串的最后一个字符,然后才依次比较第一个到第N个。
3. KMP字符串模式匹配算法
上述两种算法效率低,原因是执行过程有回溯。
在普通的字符串模式匹配算法上,当遇到主串和模式串的字符不能匹配成功时,不论已经匹配了多少字符都要进行指针回溯,再开始下一轮的匹配。这样效率是十分的低下的。KMP算法,是在朴素的模式匹配算法的基础上,实现了匹配不成功时,不对主串指针进行回溯,使模式匹配的时间复杂度降低为:O(n + m)。
KMP算法的核心思想是,在s[i] 和 p[j]不匹配时,不对主串进行指针回溯,而是在模式串中p中寻找k,用s[i] 和 p[k]进行下一轮的匹配。
在这里,将主串 S 和模式串 P 都看成是一条直线,故而在S[i] 和 P[j] 匹配不成共时,有如下情形:
图1 s[i] 和 p[j] 匹配不成功
即是:p[1…j-1] == s[i-j+1,…,i-1].
p[j] 和 s[i] 不匹配,现在要在模式串p[1,…,j-1]确定一个位置k(1<= k < j-1),用p[k]和s[i]进行下一轮匹配,那么k必须要满足以下条件:
p[1,..,k-1] == s[i-k+1, … , i-1] .
将模式串和主串都看着一条直线,那么就有下图:
图2 使用p[k]和s[i]进行下一轮匹配
由于 1<= k < j-1,那么将两图合并起来会有什么效果呢?
从上图可以看出,当s[i]和p[j]匹配不成功时,假如能用p[k]和s[i]进行下一轮匹配,则有:
s[i-k+1], … , i-1] == p[j-k+1,…,j-1] == p[1,…,k-1] 。
就是说,当s[i] 和 p[j] 匹配不成功时,最对主串不进行指针回溯,而是用p[k]和s[i]进行匹配时,k必须满足以下条件:
p[1,…,k-1] == p[j-k+1, … , j-1]。
- KMP算法的实现
KMP算法的是对匹配的模式匹配算法的改进,在s[i]和p[j]匹配不成功时,不是对主串进行指针的回溯,而是在p[1,…,j-1]中,寻找一个p[k],
用s[i]和p[k]进行下一轮的匹配。其实现的最大问题就是如何的根据p[1,…,j-1]来求出p[k]。
在KMP算法的实现中,使用一个辅助数组next[],使用该数组保存p[j]匹配不成功时,要进行下一轮匹配的k的值.即是当s[i] 和 p[j]匹配不成功时,
用p[ next[j] ]来和s[i]进行下一轮匹配,k = next[j] .
对数组next[] 的求解,可以goolge到不少的方法,这里使用最简单的递推的方法:
首先假定next[0] = –1,那么当next[j] = k时,就有:p[0,…,j-1] == p[j-k+1,…,j-1]。
这时,若有p[k] = p[j] ,则p[0,….,k] = p[j-k+1,..,j-1,j],从而就有next[j+1] = next[j] + 1 = k +1 .
若p[k] != p[j] ,可以看着模式串对自身进行匹配的问题,即当匹配失败的时候,k值如何确定,k = next [k] .