一:算法的基本思想
基本思想:
先
以主串
S
中第
pos
个字符为
S
子串的第一
个字符
,模式串
T
的长度作为
S
子串的长度,
得到一个子串去与模式串
T
中的对应字符逐个
比较,若子串与模式串相同,则返回
S
中子串
的第一个字符位置,这就是模式串在主串
S
中
的位置;
否则,取
S
中第
pos+1
个字符为子串头
,
将其往后的字符再依次和模式串
T
比较判断是
否相等,以此类推直到找到子串位置或没有
一个子串与模式串相同为止
,前者模式匹配
成功,后者模式匹配失败。
二:
算法模拟示例
主串S:ababcabcacbab 模式串T:abcac pos=1
图一
图二
图三
返回 T在S中的位置:6
三:朴素的模式匹配
主串
S=
’
ababcabcacbab
’
,
模式串
T=
’
abcac
’
↓i=3
第一趟匹配: a b a b c a b c a c b a b
a b
c
↑j=3
↓
i=2
第二趟匹配: a b a b c a b c a c b a b
a
↑
j=1
↓
i=7
第三趟匹配: a b a b c a b c a c b a b
a b c a
c
↑
j=5
↓i=4
第四趟匹配: a b a b c a b c a c b a b
a
↑j=1
↓
i=5
第五趟匹配: a b a b c a b c a c b a b
a
↑
j=1
↓i=11
第六趟匹配: a b a b c a b c a c b a b
a b c a c
(成功)
↑j=6
四:
KMP
算法。
主串S=’ababcabcacbab’,模式串T= ’ abcac’
↓
i=3
第一趟匹配: a b a b c a b c a c b a b
a b
c
↑
j=3
(next[3]=1)
↓i=3
第二趟匹配: a b a b c a b c a c b a b
a b c a
c
↑j=5 (next[5]=2)
↓
i=7
第三趟匹配: a b a b c a b c a c b a b
(a)b c a c
↑
j=2
KMP
算法
KMP—Knuth, Morris, Pratt
三人发明
特点
无需回溯
在O(n+m
)的时间量级上完成串的模式匹配操作
next
函数的定义
当此集合不空时
若模式串P为’ abaabc’,由定义可得next函数值
KMP
算法手工模拟
主串 S= ‘a c a b a a b a a b c a c a a b c’
模式串 T= ’a b a a b c’
↓
i=2
第一趟匹配: 主串 a c a b a a b a a b c a c a a b c
模式串 a
b
↑
j=2 next[2]=1
↓
i=2
第二趟匹配: 主串 a c a b a a b a a b c a c a a b c
模式串
a
↑
j=1 next[1]=0
↓
i=3
→
↓
i=8
第三趟匹配: 主串 a c a b a a b a a b c a c a a b c
模式串 a b a a b
c
↑
j=1
→
↑
j=6 next[6]=3
↓
i=8
→
↓
i=12
第四趟匹配: 主串 a c a b a a b a a b c a c a a b c
模式串 (a b) a a b c
next
函数的改进
l
当i=4,j=4时s
i
≠p
j
,由next[j]的指示还需进行i=4、j=3,
i=4、j=2,i=4、j=1等三次比较。
实际上,由于模式中第1、2、3个字符和第4个字符都相等,因此这种比较
是不必要的,可以将模式串
一次向右滑动4个字符
直接进行
i=5、j=1
的比
较。也就是说,
若
next[j]=k,当s
i
与p
j
失配
且p
j
=p
k
,则下一步不需将主串中的s
i
与p
k
比较,而是S
i
直接
与next[k]进行比较。
主串a a a b
a
a a a b
a
a a a b