在《算法》(Sedgewick)一书中,看到了KMP算法,看了一遍没懂,但觉得挺神奇的,就花费了几个小时深入的理解。
算法的原理其实不难,难的就是那个神奇的DFA数组,我的大部分时间也都是花费在这个数组上面的。
以下从豆瓣读书找来的问题及答案,看着不错,就给抠来了~
出处:http://book.douban.com/subject/19952400/discussion/59623403/
问:
5.3.3.4 构造DFA(p766)
图5.3.8 计算模式ABABAC的重启状态的DFA模拟
没看明白.
以致代码中的:
X = dfa[pat.charAt(j)][X] ;
也不能理解.
答:
dfa[text.charAt(i)][j]是指当文本字符串的字符s[i]与模式字符串的字符p[j]比较后下一次与文本字符串的字符s[i+1]比较的模式字符串的字符位。
当文本字符串的第i位字符与模式字符串的第j位进行匹配时,如果此两位字符匹配,则说明下一步应该为i++ j++之后再比较,也就是说当txt.charAt(i)==pat.charAt(j)时,有dfa[pat.charAt(j)][j]=j+1。
当文本字符串的第i位字符与模式字符串的第j位检测到不匹配时,设txt.charAt(i)==c,c!=pat.charAt(j),但文本字符串的s[i-j…i-1]这部分与模式字符串的p[0…j-1]这部分是匹配的。这时从文本字符串的i-j位置起已不可能出现匹配字符串,现在已不用管s[i-j]字符,现在的问题是依次输入s[i-j+1…i-1]c后会进入什么状态,由于s[i-j…i-1]这部分与模式字符串的p[0…j-1]这部分是匹配的,也就是说现在的问题是依次输入p[1…j-1]c后会进入什么状态。
引入一个状态指示数组X,X[j]是指正确输入p[1…j-1]后进入的状态,输入p[1…j-1]c后进入的状态就是dfa[c][X[j]](在X[j]状态时输入c),即dfa[c][j]=dfa[c][x[j]]。
而计算X[]数组的方法为递推方法:X[j+1]为正确输入p[1…j]后进入的状态,即正确输入p[1…j-1]p[j]后进入的状态,也就是在X[j]状态时输入p[j]时进入的状态,就是dfa[pat.charAt[j]][X[j]],即递推公式为:X[j+1]=dfa[pat.charAt[j]][X[j]],而X[0]手动初始化为0。
由于X[]数组为辅助数据,且为递推的,所以书中仅使用了一个变量X来指示当前的X[j],我觉得理解起来很不方便,所以这里由数组代替。
PS:看着这里,我还是糊里糊涂的,这个X的计算总是理解不了~哎~