算法导论---字符串匹配以自动机方式

1.字符串匹配

问题描述,给定一个输入字符串T[1…n],需要在T[1…n]中找到所有子串P[1…m]的起始位置。

朴素解法

对字符串T做一次遍历,遍历到元素i时,进行一次判断:从i开始到i+m-1位置是否每个T中字符均和P中对应字符相等,如相等,则输出i。

评价:简单,易用。但对每个T中字符进行处理时,没能利用到之前已经遍历的字符信息,效率不高。

基于自动机的解法

对T中所有字符做一次遍历,
以T为 abababacaba,P为ababaca为例
遍历索引:1
当前字符:a
上次为止的匹配长度:0

则,a添加后,可能的最大匹配长度为1
a与P[1]比较,
a==P[1],则匹配长度较上次增加1,

遍历索引:2
当前字符:b
上次为止的匹配长度:1
则,b添加后,可能的最大匹配长度为2
b与P[2]比较,
b==P[2],则匹配长度较上次增加1

遍历索引:3
当前字符:a
上次为止的匹配长度:2
则,a添加后,可能的最大匹配长度为3
a与P[3]比较,
a==P[3],则匹配长度较上次增加1

遍历索引:4
当前字符:b
上次为止的匹配长度:3
则,b添加后,可能的最大匹配长度为4
b与P[4]比较,
b==P[4],则匹配长度较上次增加1

遍历索引:5
当前字符:a
上次为止的匹配长度:4
则,a添加后,可能的最大匹配长度为5
a与P[5]比较,
a!=P[5],则匹配长度不可能为5
可能的匹配长度:4,3,2,1,0

对匹配长度为4进行验证:
a != P[4],故匹配长度不可能为4

对匹配长度为3进行验证:
a==P[3]
T[4]=b == P[2]
T[3]=a == P[1]
验证通过,故处理索引5后,上次为止匹配长度调整为3

遍历索引:6
当前字符:b
上次为止的匹配长度:3
则,b添加后,可能的最大匹配长度为4
b与P[4]比较,
b==P[4],则匹配长度较上次加1

遍历索引:7
当前字符:a
上次为止的匹配长度4
则,a添加后,可能的最大匹配长度为5
a与P[5]比较,
a==P[5],则匹配长度较上次加1

遍历索引:8
当前字符:c
上次为止的匹配长度:5
则,c添加后,可能的最大匹配长度为6
c与P[6]比较,
c==P[6],则匹配长度较上次加1

遍历索引:9
当前字符:a
上次为止的匹配长度:6
则,a添加后,可能的最大匹配长度为7
a与P[7]比较,
a==P[7],则匹配长度较上次加1。匹配长度达到的7,也即达到了P的长度。故从T的索引3开始,产生一次匹配

遍历索引:10
当前字符:b
上次为止的匹配长度:7
则,b添加后,可能的最大匹配长度为7【因为匹配长度不会超过P的长度,所以不会为8】
b!=P[7],则可能的匹配长度:6,5,4,3,2,1,0

b!=P[6],则匹配长度不可能为6
b!=P[5],则匹配长度不可能为5
b==P[4]
b的前一字符a,a==P[3]
a的前一字符c,c!=P[2],则匹配长度不可能为4
b!=P[3],则匹配长度不可能为3
b==P[2]
b的前一字符a,a==P[1],故匹配长度为2

遍历索引:11
当前字符:a
上次为止的匹配长度:2
则,a添加后,可能的最大匹配长度为3
a==P[3],则匹配长度较上次加1

处理完毕,产生一次匹配,匹配位置:索引3

论证:
我们的处理是多次循环迭代的过程,
每次循环迭代开始时,我们记录了上一次迭代结束时,
上次为止的最大匹配长度:k
新输入的字符:x
则,x添加后,可能的最大匹配长度为k+1。

对此进行论证,
首先,若x==P[k+1],易知,此时匹配长度较上次加1,为k+1。
假设,此时的最大匹配长度len > k+1。
则,可知上次为止的最大匹配长度为len-1>k,这与我们上次为止的最大匹配长度为k相矛盾,故,假设不成立。
即,此时,最大匹配长度为k+1。

其次,若x!=P[k+1],则匹配长度不可能为k+1
可能的匹配长度:k,k-1,…,0
对此进行论证,
若匹配长度为k+1,这显示不成立
若匹配长度len>k+1,则可知上次为止的最大匹配长度为len-1>k,这与我们上次为止的最大匹配长度为k相矛盾,故,假设不成立。
故可能的最大匹配长度为:k,k-1,…,0

综合,得证。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

raindayinrain

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值