[关闭]
@elibinary 2016-10-06T16:07:09.000000Z 字数 870 阅读 708

字符串匹配

algorithm


最近在复习一些基础算法,正好把字符串匹配的各种知识总结记录一下。关于字符串匹配我们都不陌生,例如 ruby 中 String 的 index 等一系列方法。下面先说一下最简单粗暴的解法。

先分解下问题,现在我们要解决的问题可以简单描述为这样:现有一字符串 S ,现查找目标字符串 P 在 S 中的位置。

暴力解法

所谓暴力法就是逐字符便利匹配字符串具体过程是这样的:
1. 从头部开始逐字符匹配 S 与 P,设置指针 i 指向 S 头部
2. 如果遇到字符不匹配,则令指针 i 向后移,并重头开始匹配 P
3. 重复第二步,直至成功匹配或者失配

举个简单的例子:
现有字符串 S : 'acdfcacdchd' , 现查找目标字符串 P: 'acdc'在 S 中的位置。其匹配过程是这样的:
1. 首先 S[0] 与 P[0] 比较,发现匹配,继续向后匹配 S[1] 和 P[1]
2. 直至匹配到 S[3] 与 P[3] 时,发现不匹配。向后移从 S[1] 开始匹配 P
3. 发现 S[1] 与 P[0] 不匹配,继续后移从 S[2] 开始
4. (重复过程略)
5. 发现 S[5] 与 P[0] 匹配,各自向后移一位,继续向后匹配 S[6] 和 P[1]
6. 最终完成匹配

说起来挺啰嗦,其实就是循环匹配的过程,实现起来很简单:

  1. def method_one
  2. i = j = 0
  3. while i < @a_length && j < @p_length
  4. if @string_a[i] == @string_p[j]
  5. i += 1
  6. j += 1
  7. else
  8. i = i - j + 1
  9. j = 0
  10. end
  11. end
  12. # matching complete
  13. if j == @p_length
  14. i - j
  15. else
  16. -1
  17. end
  18. end

或者下面这种写法更容易看明白,还可以通过适当剪枝来减少循环数:

  1. def method_two
  2. res = -1
  3. (0..(@a_length - @p_length)).each do |i|
  4. (0..(@p_length-1)).each do |j|
  5. break if @string_a[i + j] != @string_p[j]
  6. return i if j == @p_length - 1
  7. end
  8. end
  9. res
  10. end

经典的 KMP 算法叙述起来可能会比较繁复,就暂且再研究研究放在下次记述了。

添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注