字符串匹配(string matching)算法之二:利用有限自动机

上一篇:字符串匹配(string matching)算法之一 (Naive and Rabin_Karp)


有限自动机:

一个有限自动机M是一个5元组(Q, q0, A, Σ, δ), 其中:

·         Q是状态的有限集合

·         q0 Q 初始状态

·         A Q 是一个接受状态的集合

·         Σ 有限的输入字母表

·         δ 是从Q × Σ Q的函数, 称为M的转移函数(transition function )

有限自动机开始于状态q0,每次读入输入字符串的一个字符.

如果在状态q时读入输入字符a,则它从状态q变为δ(q, a).

当其当前状态q属于(接受状态的集合)A, 则说自动机M接受了迄今为止所读入的字符串.

没有被接受的输入称为被拒绝的输入.

有限自动机M可以推导出一个函数φ称为终态函数。φ(w)M在扫描字符串w后终止时的状态。

φ(ε)

=

q0,

φ(wa)

=

δ(φ(w), a) for w ∈ Σ*, a ∈ Σ.

因此, M接受字符串w当且仅当φ(w) A

 

字符串匹配自动机

给定模式P[1 m], 定义辅助函数σ数相应P的后缀函数.

函数σ是一个从Σ*{0, 1, . . . , m}上的映射:

σ(x)x的后缀且是p的最长前缀的长度.

σ(x) is the length of the longest prefix of P that is a suffix of x:

σ(x) = max {k : Pk x}.

例如模式P = ab, σ(ccaca) = 1, and σ(ccab) = 2

对一个长度为m的模式P来说, σ(x) = m 当且仅当 P x (Px的后缀).

给定模式P[1..m], 其对应的字符串匹配自动机的定义如下:

l        状态集Q{0, 1, …, m}, 初始状态q0, 状态m是唯一的接受状态.

l        对任意的状态q和字符a, 变迁函数δ的定义为: δ(q, a) = σ(Pqa). (其中PqP的前缀P[1..q])

也就是把状态q设为当前已匹配的长度.

例如模式P=ababaca.   文本T=abababacaba.

δ(5, b) = 4, 如果从状态q=5时自动机读入一个b, Pqb=ababab, 于是ababab的后缀匹配P的最长前缀为P4 = abab.

The longest prefix of P that is also a suffix of ababab is P4  = abab

 

//字符串匹配自动机
FINITE-AUTOMATON-MATCHER(T, δ, m)
   
   
1  n  length[T]
   
   
2  q  0
   
   
3  for i  1 to n
   
   
4      do q  δ(q, T[i])    //δ函数其实是一张表,预先计算出所有值,需要时查询
   
   
5         if q = m
   
   
6            then print "Pattern occurs with shift" im
   
   

   
   
    
     
   
   
匹配时间复杂度Θ(n).
   
   

   
   
    
     
   
   
//下面计算出δ函数
  
  
COMPUTE-TRANSITION-FUNCTION(P, Σ)
   
   
1 m  length[P]
   
   
2 for q  0 to m
   
   
3     do for each character a  Σ
   
   
4            do k  min(m + 1, q + 2)
   
   
5               repeat k  k - 1
   
   
6                 until Pk  Pqa
   
   
7               δ(q, a)  k
   
   
8 return δ
    
    
时间复杂度O(m3 |Σ|)..还存在更快的过程。
  
  

 

附录:

Σ* 表示用字母表Σ中的所有有限长度的字符串的集合

长度为0的空字符串用ε表示,ε也属于Σ*

字符串前缀  后缀

如果某个字符串 y Σ*,使得xwy ,则称wx的前缀, 记为w x 如果wx的后缀,记为w x

Introduction to Algorithms- CLRS



width="728" scrolling="no" height="90" frameborder="0" align="middle" marginwidth="0" marginheight="0" src="http://download1.csdn.net/down3/20070601/01184120111.htm">
  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
### 回答1: BF算法,也称为暴力匹配算法,是一种简单的字符串匹配算法。它的基本思想是从主串的第一个字符开始,依次与模式串的每一个字符进行比较,如果匹配成功,则继续比较下一个字符,否则主串向右移动一位,重新开始匹配。 具体实现步骤如下: 1. 定义主串和模式串两个字符串。 2. 从主串的第一个字符开始,依次与模式串的每一个字符进行比较。 3. 如果匹配成功,则继续比较下一个字符,直到模式串的最后一个字符都匹配成功。 4. 如果匹配失败,则主串向右移动一位,重新开始匹配。 5. 如果主串的长度小于模式串的长度,则匹配失败。 6. 如果主串的长度等于模式串的长度,且每个字符都匹配成功,则匹配成功。 下面是一个简单的BF算法实现代码: ``` #include <iostream> #include <string> using namespace std; int BF(string s, string p) { int i = 0, j = 0; while (i < s.length() && j < p.length()) { if (s[i] == p[j]) { i++; j++; } else { i = i - j + 1; j = 0; } } if (j == p.length()) { return i - j; } else { return -1; } } int main() { string s = "hello world"; string p = "world"; int pos = BF(s, p); if (pos == -1) { cout << "not found" << endl; } else { cout << "found at position " << pos << endl; } return 0; } ``` 在上面的代码中,BF函数接受两个字符串参数s和p,分别表示主串和模式串。函数返回值为匹配成功的位置,如果匹配失败则返回-1。在函数中,使用两个指针i和j分别指向主串和模式串的第一个字符,依次进行比较。如果匹配成功,则i和j都向后移动一位;如果匹配失败,则i回退到上一次匹配的下一个位置,j回退到模式串的第一个字符。最后,如果j等于模式串的长度,则表示匹配成功,返回i-j的值即可。 ### 回答2: bf算法(Brute-Force 算法)是一种简单的字符串模式匹配算法。它的思想是通过对两个字符串逐个字符进行比较来判断字符串是否匹配。以下是用Python编写的一个简单的bf算法实现: ```python def pattern_matching(text, pattern): n = len(text) m = len(pattern) for i in range(n-m+1): j = 0 while(j < m): if (text[i+j] != pattern[j]): break j += 1 if (j == m): return i return -1 text = 'ABCABCDABABCDABCDABDE' pattern = 'ABCDABD' index = pattern_matching(text, pattern) if (index == -1): print("无匹配结果") else: print("匹配结果在字符串中的索引位置为:", index) ``` 在上述代码中,pattern_matching函数接受两个参数text和pattern,其中text是待匹配的字符串,pattern是需要匹配的字符串。程序通过逐个字符比较来判断字符串是否匹配。如果找到了匹配的子串,则返回匹配的子串在text中的索引位置。如果没有找到匹配的子串,则返回-1。 例如,在上述示例中,待匹配的字符串是'ABCABCDABABCDABCDABDE',需要匹配的字符串是'ABCDABD'。由于该模式在主字符串中存在,所以匹配结果在字符串中的索引位置为6。 通过bf算法,我们可以快速实现一个简单的字符串模式匹配算法。然而,bf算法的时间复杂度较高,在最坏情况下为O(n * m),其中n为主字符串的长度,m为模式字符串的长度,因此在处理大规模的字符串匹配时,可能不适用。 ### 回答3: BF(Brute Force)算法,也称为朴素模式匹配算法,是一种简单的模式匹配算法。它的基本思想是,从文本串的起始位置开始逐个字符与模式串进行比较,当发现不匹配时,将文本串向右移动一位,再重新开始比较。当匹配成功时,返回模式串在文本串中的起始位置,否则返回-1。 以下是使用Python编写的BF算法的实现: ```python def BF(pattern, text): pattern_len = len(pattern) text_len = len(text) for i in range(text_len - pattern_len + 1): found = True for j in range(pattern_len): if pattern[j] != text[i+j]: found = False break if found: return i return -1 ``` 使用该算法进行模式匹配的示例: ```python text = "Hello, world!" pattern = "world" index = BF(pattern, text) if index == -1: print("未找到匹配的模式") else: print("模式在文本中的起始位置为:", index) ``` 运行结果为: ``` 模式在文本中的起始位置为: 7 ``` 在上述代码中,`BF`函数接受两个参数,分别是待匹配的模式串`pattern`和文本串`text`。首先计算模式串和文本串的长度,并使用两个循环来逐个比较字符。如果发现不匹配,则将文本串向右移动一位,再重新开始比较。如果匹配成功,则返回模式串在文本串中的起始位置,否则返回-1。 以上就是简单模式匹配算法(BF算法)的Python实现。由于BF算法的时间复杂度较高,通常在处理大规模的模式匹配问题时会选择更高效的算法

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值