Knuth-Morris-Pratt算法中的DFA构造

时间:2015-05-30 15:52:40

标签: string algorithm substring dfa knuth-morris-pratt

我指的是Sedgewick的书“算法”(第4版)中用于子串搜索的Knuth-Morris-Pratt(KMP)算法的大纲。

KMP算法在子串搜索中使用基于确定性有限自动机(DFA)的备份。我了解DFA如何输入算法,但我不明白如何构建 DFA,这由以下代码片段完成:

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];
}

其中M是模式pat的长度,R是字母表的大小。 charAt()函数返回相应位置的字符的整数值。

有人可以解释这段代码构造dfa的方式吗?我迷失在内部for循环的实际直观意义中。

1 个答案:

答案 0 :(得分:10)

让我们看看下面的FA模式ACACAGA。

enter image description here

enter image description here

上图显示了ACACAGA模式的图形和表格表示。

这里,DFA中的状态数是M + 1,其中M是模式的长度。构造DFA的主要任务是从每个可能的角色的当前状态获取下一个状态。给定一个字符x和一个状态k,我们可以通过考虑字符串“pat [0..k-1] x”得到下一个状态,这基本上是模式字符pat [0],pat 1的串联... pat [k-1]和角色x。想法是获得给定模式的最长前缀的长度,使得前缀也是“pat [0..k-1] x”的后缀(LPS)。长度值给我们下一个状态。

例如,让我们看看如何从上图中的当前状态5和字符“C”获取下一个状态。我们需要考虑字符串“pat [0..5] C”,即“ACACAC”。模式的最长前缀的长度使得前缀是“ACACAC”的后缀是4(“ACAC”)。所以下一个状态(来自状态5)对于字符'C'是4。

protostuff-maven-plugin