【数据结构与算法】String-02 KMP和有限状态自动机

来源:《算法》第四版 第五章

1、暴力字符匹配算法

public static int search(String pt, String txt){
	int j, M = pat.length();
	int i, N = txt.length();
	for(i = 0, j = 0; i < N && j < M; i++){
		if(txt.charAt(i) == pat.charAt(j)) j++;
		else{ i -= j; j = 0;}
	}
	if(j == M) return i - M;	//找到匹配
	else return N;				//未找到匹配
}

  可以看到,第6句,每次匹配失败的时候,i 就会回退一些。这样在最坏的情况下,就造成了效率的低下。所以,我们不希望每一次 i 都回退到上一次匹配的开头,我们希望可以利用我们已经使用过的信息来完成回退的减少。

2、DFA考虑回退

  和大多数的教程不同,大多数的教程是用 next[] 数组来运算和记录它的会退,而《算法》中,采用了更好理解的 DFA(deterministic finite automation,确定有限状态自动机),比如对于 pattern字串“ABABAC”,根据这个字串就能确认它所对应的自动机:
在这里插入图片描述

  同时,它的 dfa[][] 也能很快的确定下来了,那根据我们画出的 自动状态机,我们去匹配各个字符串,以及清楚的知道它们的回退机制之后,我们就能很快的在 text字串 中开始O(N+M)复杂度的匹配了。
在这里插入图片描述

  dfa[][] 第一个 [] 中填充的是,i 所指的字符在字母表中的序号,第二个 [] 是 j ,也就是 pattern 中的第几个字符。在这个例子中,pattern的长度为6,也就是当 j 达到 6 的时候就已经是 自动状态机的停止状态了。

3、构造DFA

  当我们在匹配 i 指针 和 j 指针的字符的失败的时候,i 指针每次依然在前进,j 指针所执行的操作不像是回退,而更像是 状态自动机 中的状态重置。
  所以,我们现在只考虑它的重启状态:我们在扫描当前的 字符的值 的之前,就已经可以通过之前的已知信息来知道:如果它失败了,它应当回退到什么位置去。

在这里插入图片描述

  我们在以下的构造流程中,可以清楚的看到,模板 X 的走向会因为输入的变化而变化。
在这里插入图片描述

  构造出来的感觉就比较像是 KMP中的next[]数组。它的构造过程就分为 3 个步骤:

① 将dfa[][X]复制到dfa[][j](对于匹配失败的情况);
② 将dfa[pat.charAt(j)][j]设为 j+1(对于匹配成功的情况);
③ 更新X

dfa[pat.charAt(0)][0] = 1;
for(int X = 0,j = 1; j < M; j++){
	for(int c = 0; c < R; c++){
		dfa[c][j] = dfa[c][X];
	}
	dfa[pat.charAt(j)][j] = j + 1;
	X = dfa[pat.charAt(j)][X];
}
  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值