与有限自动机匹配的字符串

时间:2012-01-06 11:55:04

标签: string algorithm

我正在阅读Cormen的书“算法导论”中的字符串算法。对于Transition,如下所示。

我的问题:我们为什么要做min(m+1, q+2),为什么我们将m增加1,q增加2.

以下链接已回到上述问题。

http://people.scs.carleton.ca/~maheshwa/courses/5703COMP/Fall2009/StringMatching.pdf

请用一个简单的例子来帮助。

Algorithm Compute-Transition-Function(P, Sigma)
m = length(P);
for  q = 0 through m  do
   for each character  x  in Sigma
       k = min(m+1, q+2);
       repeat  k = k-1  // work backwards from q+1
       until  Pk 'is-suffix-of' Pqx;
       d(q, x) = k; // assign transition table
   end for;
end for;

return  d;
End algorithm.

3 个答案:

答案 0 :(得分:2)

  • 它是m + 1,因为在下一个repeat循环k首先减少。
  • 它是q + 2,因为在repeat中您以q + 1开始,因此至少有1个字符。

以下代码可能存在边界问题(缺少q == m), 但希望使索引更清晰。

m = length(P);
for  q = 0 through m - 1 do // Loop through substrings [0, q+1]
   for each character  x  in Sigma
       k = q+1;
       // work backwards from q+1
       while not Pk 'is-suffix-of' Pqx;
       do k = k-1; end do;
       d(q, x) = k; // assign transition table
   end for;
end for;

return  d;

答案 1 :(得分:1)

代码已经解释过,所以这里有一个例子来看看发生了什么

假设字符串为nano

所以我们希望我们的状态与模式部分匹配。与"nano"可能的部分匹配是 "", "n", "na", "nan", or (the complete match) "nano"本身。换句话说,它们只是字符串的前缀。一般来说,如果模式有m个字符,我们需要m + 1个状态;这里m = 4,有五个州。

如果我们刚看到"...nan",并看到另一个角色"x",我们应该去哪个州?显然,如果x是匹配中的下一个字符(这里是“o”),我们应该转到下一个更长的前缀(这里是“nano”)。很明显,一旦我们看到完全匹配,我们就会保持这种状态。但是假设我们看到了不同的角色,例如"a"?这意味着到目前为止,字符串看起来像"...nana"。我们可以进行的最长部分匹配仅为"na",即我们可以使用最后2个字符。因此,从州"nan"开始,我们应该绘制一个标有"a"的箭头来表示"na"。请注意,"na""nano"的前缀(因此它是一个状态),后缀为"nana"(所以它是与我们刚看到的一致的部分匹配)。

通常,从状态+字符到状态的转换是最长的字符串,它同时是原始模式的前缀和我们刚看到的状态+字符的后缀。这足以告诉我们所有转换应该是什么。如果我们要查找模式"nano",则转换表将是

     n       a       o      other
    ---     ---     ---     ---
empty:  "n"     empty   empty   empty       
"n":    "n"     "na"    empty   empty
"na":   "nan"   empty   empty   empty   
"nan":  "n"     "na"    "nano"  empty    //just as an illustration, nan + n = n because we can only use the last 'n', nan + a = na because now we can use the last two 'na'
"nano": "nano"  "nano"  "nano"  "nano"

现在我们如何使用这个表来实际进行模式搜索?

在字符串"banananona"上模拟这个,我们通过一次移动一个字符来获得状态序列为空,空,"n", "na", "nan", "na", "nan", "nano", "nano", "nano"。由于我们以状态"nano"结束,因此该字符串在其中包含"nano"。所以让我们来看看最新情况以及如何使用上面的表格,在'b',我们没有任何可能的状态'n', 'na', 'nan', 'nano'。因此它被视为空...与我们到达'ba'时相同。当我们点击下一个字符'n'时,我们基本上是从空到n,所以我们使用上面的表格并看到它以'n'结束。现在我们得到了banananona的4个字符,所以我们从'n'开始添加...再次我们使用该表并看到它最终处于状态'na',依旧等等......

答案 2 :(得分:0)

转换表中的条目d(q,x)包含使用字符x后模式的最长匹配前缀的长度,如果在使用x之前,最长匹配前缀为{{ 1}}字符长。由于我们使用一个字母,因此不能大于q,并且由于该模式的长度为q+1,因此它最多也可以为m。内部循环为m,因此在测试任何内容之前,repeat k = k-1 until condition(k)会递减,因此k必须比最大可能结果k开始大1。如果内部循环是k = min(m,q+1) + 1,则会以while negated_condition(k) { k = k-1; }开头。

请注意,通过使用Knuth-Morris-Pratt算法的边界表,可以更有效地计算转换表。