(Translated by https://www.hiragana.jp/)
KMP算法 - 维基百科,自由的百科全书 とべ转到内容ないよう

KMP算法さんぽう

本页使用了标题或全文手工转换
维基百科ひゃっか自由じゆうてき百科ひゃっかぜん
ざい本文ほんぶんちゅうはた使用しようはじめ于零てきすうらい表示ひょうじくし如,わかくしS = "ABC",则S[2]表示ひょうじ'C'。这种表示ひょうじ方法ほうほうあずかC语言一致いっち

ざい计算つくえ科学かがくなかかつつとむ斯-莫里斯-ひろしひしげとくくし查找算法さんぽう英語えいごKnuth–Morris–Pratt algorithm,简称为KMP算法さんぽうざいいちくしSうち查找いち个词Wまと位置いちいち个词ざいひきはい本身ほんみ包含ほうがんあし够的しんいきらい确定一个匹配可能的开始位置,此算ほう利用りよう这一特性以避免重新检查先前配對的

这个算法さんぽうゆかり高德こうとく沃恩·ひしげとくざい1974ねん构思,同年どうねん詹姆斯·H·莫里斯也独立地りっち设计该算ほうさいさんにん于1977ねん联合发表。

查找过程

[编辑]

W="ABCDABD"S="ABC ABCDAB ABCDABCDABDE"为例说明查找过程。查找过程どう使用しよう两个循环变量mi

  • m代表だいひょうぬし文字もじくしSうちひきはいくしWてきとうぜん查找位置いち
  • i代表だいひょうひきはいくしWとうぜん做比较的位置いち

图示如下:

             1         2  
m: 01234567890123456789012
S: ABC ABCDAB ABCDABCDABDE
W: ABCDABD
i: 0123456

したがえWあずかSまとひらきあたま比較ひかくおこりたいいたS[3](=' ')とき發現はつげんW[3](='D')あずかこれせっちょなみしたがえS[1]比較ひかくやめけい知道ともみちS[1]~S[3]あずかW[0]相合そうごうよし此,ほぼ這些もとれいm = 4以及i = 0

             1         2  
m: 01234567890123456789012
S: ABC ABCDAB ABCDABCDABDE
W:     ABCDABD
i:     0123456

如上じょじょうしょしめせけんかくりょう"ABCDAB"這個くししか而,したいち便びん相合そうごう注意ちゅういいた"AB"ざい"ABCDAB"てきあたましょひとしゆう出現しゅつげん。這意あじちょ尾端びたんてき"AB"作為さくい比較的ひかくてきおこり始點してんよし此,れいm = 8, i = 2繼續けいぞく比較ひかく圖示ずし如下:

             1         2  
m: 01234567890123456789012
S: ABC ABCDAB ABCDABCDABDE
W:         ABCDABD
i:         0123456

m = 10てき地方ちほうまた出現しゅつげんあいてき情況じょうきょう類似るいじれいm = 11, i = 0繼續けいぞく比較ひかく

             1         2  
m: 01234567890123456789012
S: ABC ABCDAB ABCDABCDABDE
W:            ABCDABD
i:            0123456

這時,S[17](='C')あずかW[6]あいどうただしやめひきはい部分ぶぶん"ABCDAB"また首尾しゅびひとしゆう"AB"採取さいしゅ一貫いっかんてき作法さほうれいm = 15i = 2繼續けいぞくさがせひろ

             1         2  
m: 01234567890123456789012
S: ABC ABCDAB ABCDABCDABDE
W:                ABCDABD
i:                0123456

找到完全かんぜんひきはいてきくしりょう,其起はじめ位置いちS[15]てき地方ちほう

部分ぶぶんひきはいひょう

[编辑]

部分ぶぶんひきはいひょうまたたたえしつはい函数かんすう作用さよう让算ほう无需つぎひきはいSなかてきにんなんのう够实现线せい时间搜索そうさくてき关键ざいしゅくしてき一些字段中检查模式串的はつはじめだん以确切地きれじ知道ともみちざいとうぜん位置いちまえてき一个潜在匹配的位置。换句话说,ざい错过にんなん潜在せんざいひきはいてきじょう况下,"预搜索そうさく"这个しきくし本身ほんみ并将其译なりいち包含ほうがん所有しょゆう可能かのうしつはいてき位置いち对应以绕过最无效てきれつひょう

对于Wなかてきにんなん位置いち希望きぼうのう够查询那个位置いちまえ包括ほうかつ位置いちゆう可能かのうてきWてきさい长初はじめだんてき长度,而不是重これしげしんW[0]开始较整个字だん,这长就是查找一个匹配时回退的距离。よしT[i]これWてき可能かのうてき适当はつはじめだんどう时也结束于W[i - 1]てきくしてき最大さいだい长度。使つかいそらくし长度0。とう一个失配出现在模式串的最开始,这是特殊とくしゅじょう况(无法かい退すさ),设置T[0] = -1ざい下面かめん讨论。

创建ひょう算法さんぽうしめせれい

[编辑]

W = "ABCDABD"为例。以下いかはたいた部分ぶぶんひきはいひょうてき生成せいせい过程あずか前述ぜんじゅつ查找过程大同だいどうしょう异,且出于类原因げんいんだかこうてき

くびさき,设定T[0] = -1。为求T[1],必须找到いち"A"てききさききさき缀指不等ふとう于原くしてききさき缀)けんWてきぜん缀。ただし"A"ぼつゆうきさき缀,所以ゆえん设定T[1] = 0。类似T[2] = 0

继续到T[3]注意ちゅういいた检查所有しょゆうきさき缀有いち捷径しょうけいかり存在そんざい符合ふごう条件じょうけんてきぜんきさき缀,两者ぶん别为W[0..1] = W[1..2],则必ゆうW[0..0] = W[1..1]よしW[0..0]またこれWてき真前まんまえ缀,うえ一步必然已经得到T[2] = 1(而有T[2] = 0,说明かり设不成立せいりつ)。一般いっぱんへん历到ごと个字时,ただゆうじょう一步已经发现一个长为mてき有效ゆうこうきさき缀,さい需要じゅよう判断はんだんゆう无长为m+1てききさき缀,而毋需考虑长为m+2、m+3とうてききさき缀。

从而,必考虑长为2てききさき缀,而唯どく需要じゅようこう虑的长度1また不可ふかぎょういたT[3]=0

せっらいW[4] = 'A'もと于同样的理由りゆう需要じゅようこう虑的最大さいだい长度为1,并且ざい'A'这个じょう况中有效ゆうこうかい退すさいた寻找てきとうぜんこれまえてきだんいんT[4] = 0

现在こう虑下いち个字W[5] = 'B'使用しよう这样てき逻辑:如果曾发现一个子模式在上一个字符W[4]これ前出ぜんしゅつ现,继续いたとうぜんW[5]么在它之ぜん本身ほんみかい拥有一个结束于W[4]ごう适的はつはじめだんあずかこと相反あいはんてきやめ经找到'A'さい早出そうしゅつ现在结束于W[4]てきごう适字だんよし此为りょう找到W[5]てき终止くし需要じゅよう查看W[4]よしT[5] = 1

さいきさきいたW[4] = 'A'したいち个字'B',并且这也确实W[5]。此外,上面うわつらてきしょうどうさんすう说明为了查找W[6]てきだん需要じゅようこうぜん查看W[4]所以ゆえんとくT[6] = 2

于是いた下面かめんてきひょう

i 0 1 2 3 4 5 6
W[i] A B C D A B D
T[i] -1 0 0 0 1 2 0

另一个更复杂和有趣的例子:

i 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
W[i] P A R T I C I P A T E I N P A R A C H U T E
T[i] -1 0 0 0 0 0 0 1 2 0 0 0 0 0 0 1 2 3 0 0 0 0 0 0

建立こんりゅうひょう算法さんぽうてき伪代码的かい

[编辑]

上面うわつらてきれい最少さいしょうてき复杂展示てんじりょう组织这个ひょうかくてき一般いっぱんせい方法ほうほう。这么做的原理げんり整体せいたいてき搜索そうさくだい多数たすう工作こうさくやめ经在检测いたとうぜん位置いちてき时候做完了かんりょうあましも需要じゅよう做的很少。りゃくほろ复杂てき一点是找到一个共同前后缀。这就需要じゅようゆう一些初始化的代码。

algorithm kmp_table:
    input:
        an array of characters, W (the word to be analyzed)
        an array of integers, T (the table to be filled)
    output:
        nothing (but during operation, it populates the table)

    define variables:
        an integer, pos ← 2 (the current position we are computing in T)
        an integer, cnd ← 0 (the zero-based index in W of the next 
character of the current candidate substring) (the first few values are fixed but different from what the algorithm
might suggest) let T[0] ← -1, T[1] ← 0 while pos < length(W) do (first case: the substring continues) if W[pos - 1] = W[cnd] then let cnd ← cnd + 1, T[pos] ← cnd, pos ← pos + 1 (second case: it doesn't, but we can fall back) else if cnd > 0 then let cnd ← T[cnd] (third case: we have run out of candidates. Note cnd = 0) else let T[pos] ← 0, pos ← pos + 1

建立こんりゅうひょうてき算法さんぽうてき效率こうりつ

[编辑]

建立こんりゅうひょうてき算法さんぽうてき复杂,其中これWてき长度。

除去じょきょ一些初始化的工作,所有しょゆう工作こうさくざい循环ちゅう完成かんせい。为说あかり循环执行ようりょうてき时间,こうpospos - cndてき大小だいしょう

  • ざいだいいち个分ささえさとpos - cnd变,而posあずかcndどう时自ぞう自然しぜんpos增加ぞうかりょう
  • ざいだい个分ささえさとcndさらしょうてきT[cnd]ところがえだい,从而增加ぞうかりょうpos - cnd
  • ざいだいさん个分ささえさとpos增加ぞうかりょう,而cnd变,所以ゆえんpospos - cnd增加ぞうかりょう

いんpos ≥ pos - cndそくざいまい一个阶段要么pos增加ぞうかようposてきいち个下かい增加ぞうかすんでしか算法さんぽうざいpos = n时终どめ,此循环必しかざい最多さいた迭代きさき终止。よし建立こんりゅうひょうてき算法さんぽうてき复杂

另见

[编辑]

外部がいぶ連結れんけつ

[编辑]

引用いんよう

[编辑]