美文网首页
[算法] 字符串匹配

[算法] 字符串匹配

作者: 舒也ella | 来源:发表于2019-01-10 10:49 被阅读0次

问题定义

文本T[1..n] 模式P[1..m]
找到所有的偏移s(0<=s<=n-m),使得PT_{s+m}的后缀
前缀符号\sqsubset 后缀符号\sqsupset
后缀重叠引理 前缀和后缀关系为传递关系

运行时间

运行时间 = 预处理时间 + 匹配时间


朴素匹配算法

如果模式中所有字符都不相同,运行时间可达O(n*m)

Rabin Karp算法

PT_0, T_1...T_{n-m}预处理为以d为基数表示的数字:
P的预处理时间为\Theta(m)
T的预处理时间使用下式计算为\Theta(n-m+1):
t_{s+1} = (d(t_s - T[s+1]h) + T[s+m+1]) \;mod\; q
h = d^{m-1} \; mod \;q
如果t_s = p\; (mod \; q)说明该偏移s为伪命中点,可进行循环检测P[1..m] = T[s+1..s+m],最坏匹配时间\Theta((n-m+1)m),期望匹配时间O(n)

有限自动机匹配

符号定义

有限自动机M(Q, q_0, A, \Sigma, \delta)
后缀函数\sigma(x)是能作为x的后缀的P的最长前缀长度
\sigma(x)=max ( k: P_k \sqsupset x)

预处理阶段

构造模式串的字符串匹配自动机
状态Q={1,2..m},q_0为0,状态m为唯一接受状态(但m也需要求状态转移函数)
\delta(q, a) = \sigma(P_qa)

  • 计算转移函数
Compute-transition-function
m = P.length
  for q = 0 to m
    for each character a in \Sigma
     k = min(m, q+1)
     while P_k 不是P_q+a的后缀
        k--
     \delta(q,a) = k
return \delta

时间复杂度O(m^3 |\Sigma|)

  • 利用kmp中的π求此处的转移函数可以将时间复杂度降低为​O(m|\Sigma|)
    因为\delta(q, a) = \sigma(P_qa),所以有\delta(\pi[q], a) = \sigma(P_{\pi[q]}a),而\pi[q] = max(k : k < q 且 P_k \sqsupset P_q)表示能构成P_q真后缀的P的最长前缀长度,\sigma(P_qa)=max ( k: P_k \sqsupset P_qa)表示能构成P_qa的后缀的P的最长前缀长度,因此,\sigma(P_qa) = \sigma(P_{\pi[q]}a)。同时如果q!=mP[q+1]=a那么\delta(q,a)直接等于q+1即可,综合可得,如果 q == mP[q +1] !=a那么​\delta(q,a) = \delta(\pi[q],a)。根据上式利用前缀函数​\pi只需m次循环便可计算得到转移函数,时间复杂度为​O(m|\Sigma|)
COMPUTE-TRANSITION-FUNCTION(P, Σ)
    π = COMPUTE-PREFIX-FUNCTION(P)
    for a ∈ Σ 
        δ(0, a) = 0
    δ(0, P[1]) = 1
    for a ∈ Σ 
        for q = 1 to m 
            if q == m or P[q + 1] != a 
                δ(q, a) = δ(π[q], a)
            else
                δ(q, a) = q + 1
匹配阶段
Finite-automation-matcher
n = T.length
q = 0
for i = 0 to n-1 
  q = \delta(q, T[i])
  if q == m
    print i - m

时间复杂度\Theta(n)

Knuth Morris Pratt算法

符号定义

前缀函数 \pi[q]是能构成P_q后缀的P的最长前缀长度
\pi[q] = max(k : k < q 且 P_k \sqsupset P_q)

预处理阶段

摊还分析,时间复杂度\Theta(m)

Compute-prefix-function
m = P.length
pi[1] = 0
k = 0
  for q = 2 to m
    while k > 0 and P[k+1] != P[q]
      k = pi[k]
     if P[k+1] == P[q]
        k++
     pi[q] = k
return pi

注意!前缀函数所要求的真后缀是指k必须满足小于q,例如模式串首个字符的后缀本身必定也是它的前缀,但k==q,因此此处赋值为0(字符串从1开始, 如果从0开始应赋值为-1)

匹配阶段

摊还分析,时间复杂度\Theta(n)

KMP-Matcher
n = T.length
m = P.length
pi = Compute-prefix-function
q = 0
for i = 1 to n
  while q > 0 and P[q+1] != T[i]
    q = pi[q]
  if P[q+1] == T[i]
    q++
  if q == m
    print i - m
    q = pi[q]

Boyer Moore算法

相关文章

  • 字符串匹配

    indexOf 底层就是使用字符串匹配算法 字符串匹配算法很多 BF( Brute Force)算法 暴力匹配算...

  • KMP字符串匹配算法

    KMP字符串匹配算法 先总结一下之前的几种字符串匹配算法 1 BF算法, 最简单的字符串匹配算法, 可以直接使用s...

  • KMP算法文章合集

    字符串的查找:朴素查找算法和KMP算法 暴力匹配算法与KMP算法(串的匹配) 字符串查找算法BF和KMP 字符串匹...

  • 一些有关算法的

    字符串模式匹配算法 字符串的KMP算法详解部分匹配表(即)向右移一位就可以得到next数组。字符串模式匹配算法 R...

  • 字符串匹配算法

    场景:字符串A为主串,字符串B为模式串,比较字符串B是否能够在字符串A中进行匹配? 匹配算法:BF算法和RK算法。...

  • 字符串匹配算法

    以下为学习 《数据结构与算法之美 -- 字符串匹配》 的记录。 BF算法 即暴力匹配算法,循环遍历匹配。 RK算法...

  • 2022-01-25

    1.字符串匹配BM算法 在文本中查找字符串匹配算法,坏字符串规则和好后缀规则坏字符串规则: 从后往前匹配,第一个不...

  • 20-字符串匹配

    字符串匹配 这章节,我们会讲到几大典型的字符串匹配算法 BF算法 BF算法是最最符合正常人逻辑思维的一种匹配模式,...

  • leetcode字符串匹配算法之KMP算法

    本篇介绍一种高效的字符串匹配算法——KMP算法。 KMP算法是一种改进的字符串匹配算法,由D.E.Knuth,J....

  • 中文分词的方法

    1、基于字符串匹配的方法 1.1 正向最大匹配分词算法1.2 逆向最大匹配分词算法1.3 双向最大匹配分词算法1....

网友评论

      本文标题:[算法] 字符串匹配

      本文链接:https://www.haomeiwen.com/subject/ryxnrqtx.html