Talk:Knuth–Morris–Pratt algorithm

message: Removed the following text from the article, for I'm not sure if it's correct.  It is clear, however, that it's not C, but rather a hybrid between C and Pascal... 
The following implementation is written in C:
 INPUT: Text T[0,n-1], Pattern P[0,m-1]
 Output alle matches of P in T
 InitNext(P);
 j=0;
 for (i=1;i<=n;i++)
 {
    while ((j>0) && (P[j+1] != T[i]))
    {
       j=next[j];
    }
    if (P[j+1] == T[i])
       j++;
    if (j == m-1)
    {
       print "Found P";
       j = next[j];
    }
 }
 Procedure InitNext(P)
 Input: Pattern P
 next[1] = 0;
 for (q=2;q<=m;q++)
 {
    while ((l>0) && (P[l+1] != P[q]))
    {
       l = next[l];
    } 
    if (P[l+1] == P[q])
       l++;
    next[q] = l;
 }
— Preceding unsigned comment added by Madoka (talk • contribs) 03:19, 24 March 2004 (UTC)
thread_title: Early text

message: First, I've removed the rather antique discussion topic that was already here, as the article has been revised substantially since then and anyway, it was more than a year old.
Second, are there any thoughts on whether I should replace the verbal algorithms with the plain C code?  Barely any knowledge of C is necessary to comprehend what is going on in the code; I have tried to write it in such a way that it avoids all idioms even at the cost of being a little too verbose, and the language itself is self-documenting in its usage for the most part.  But now that the code is there it seems to reproduce very closely the English-language algorithms and creates a redundancy.  I think, given the choice, I would rather keep the code, since it's clearer for the most part, in addition to being more useful, but then, I am comfortable with C and others may not be.  So, keep both forms, or just one?
:The verbal description reflects the C description too closely, probably because it was written to the C description. Replace it with something more high-level, if you can. No verbal description should say stuff like "if i > 0, set i = e." Deco 07:59, 8 December 2005 (UTC)
replies: text: There are two verbal descriptions of the code; the lengthy example was the first thing written (actually, it was the reason I rewrote the article, since in the original it was all there was, and quite bad).  The second verbal description, which I wrote in vague emulation of Knuth's style for describing algorithms, was written to the C code after I decided that it was unwise to have the only formal description of the algorithm written in a single programming language that some casual readers might not know.  Those who do know can verify the two are the same and, if curious, can compile my code and run the algorithm.  Ryan Reich 14:12, 21 February 2006 (UTC)

text: When an old discussion is taking up space on a talk page, please archive it instead of deleting it! ᛭ LokiClock (talk) 13:35, 28 May 2010 (UTC)
thread_title:  First, I've removed... 

message: Mistake? "Thus in the fourth step, m = 0 and i = 3."  should that be m = 3 and i = 3? — Preceding unsigned comment added by 70.27.57.14 (talk) 06:10, 8 December 2005 (UTC)
thread_title:  Mistake? "Thus, in the fourth step..." 

message: In the The efficiency of the search algorithm section, the second paragraph starts:
*Using this fact, we will show that the loop can execute at most l times.
but the third paragraph has this contradiction:
*Thus the loop executes at most 2l times,
It seems it should be 2l times (for example searching AAAAA for AB, if I've read the code right), so
I changed it.
Secondly I tried but failed to make the math tags work on the letters l, m i, and so on, but they
stayed obstinately unclear (1 l and I looked practically indistinguisale on my browser) so I resorted to boldifying each math term. I guess there's some preference setting for making the < math > terms look consistent? -Wikibob 02:23, 18 December 2005 (UTC)
replies: text: That's a fine solution.  Computer users have been unable to distinguish the letters l and I, and the number 1, for at least the last fifteen years.  I blame the invention of Times New Roman. Ryan Reich 14:12, 21 February 2006 (UTC)
thread_title:  In the ''the efficiency of the search algorithm'' section... 

message: Is the line below supposed to read "T[i-1]" instead of "T[i+1]"?--
  
"...T[i] in the code is equivalent to T[i + 1] above..."
:Yeah... Ryan Reich 14:12, 21 February 2006 (UTC)
thread_title:  T[i-1] instead of T[i+1]? 

message: Shouldn't O(n) + O(1) be O(n) and not O(n+1)? Constants are not taken into account in O() notation. PedroCR
: You're talking about the very last section?  That's not a 1 ("one"), it's a l ("ell").  It's the length of the string. Ryan Reich 12:10, 10 April 2006 (UTC)
replies: text: Maybe it would be better to write uppercase 'L' and 'N', but lowercase 'i'? T0ljan 12:53, 17 April 2006 (UTC)
thread_title:  O(n+l) 

message: Since some IP editor decided that it would be neat to write Java code for this algorithm, I realized that having any language-specific code in here is a bad idea.  Of course, the Java code was practically identical to the C code, with minor differences mostly centered on how the length of a string is determined, so it added nothing.  I've replaced my C code, their Java code, and also my previous attempt at pseudocode with new pseudocode formatted as suggested in the WikiProject Computer Science manual of style.  If you are a future editor reading this article, and for some reason you also read the talk page before editing, please don't implement the algorithm in your favorite language, as it adds nothing.  I've also warned you in the page's source. Ryan Reich 19:10, 10 August 2006 (UTC)
thread_title:  Code -> pseudocode 

message: The algorithm described in Item 179 of HAKMEM seems quite similar to KMP, despite that HAKMEM is from 1972 so it predates the publication by KMP.  Were variants of the algorithm for fast string matching known long before this publication or am I misinterpreting something?  Should this be mentioned in the article?  Thanks,  – b_jonas 19:07, 9 November 2006 (UTC)
replies: text: I've now also asked this at the Reference desk/Mathematics.  – b_jonas 15:53, 29 September 2007 (UTC)

text: That HAKMEM entry is cited by Knuth in "Selected Papers on Design of Algorithms" Chapter 9 "Fast Pattern Matching in Strings" for the idea of inlining the table into the search loop when compiling to machine instructions, but not for the original idea. Perhaps also cited in the paper from 1977? Aureooms (talk) 16:10, 10 May 2021 (UTC)
thread_title:  History of the algorithm 

message: What is terminal substring (this term is used w/o definition and I cannot find one with google)? 217.21.164.43 09:18, 10 October 2007 (UTC)
replies: text: Perhaps I was writing too much under the influence of mathematical jargon (though you won't find it there either).  "Terminal" just means "at the end", so a "terminal substring" of a string S is a substring located at the end of S.  For example if S is the string "abcdefg", then the substrings "efg" and even "bcdefg" are terminal, whereas "a" and "cde" are not (to pick just a few examples). Ryan Reich 13:40, 10 October 2007 (UTC)
replies: text:  Somehow, I'd feel a LOT more comfortable if somebody used "proper prefix" or "proper suffix" rather than "proper initial substring" or "proper terminal substring". I mean, it's a mouthful of syllables that clutters the rest of the article --202.168.251.139 16:22, 10 October 2007 (UTC)
replies: text:  Here's an opportunity to gain comfort with editing Wikipedia, then.  Why don't you change the terminology you don't like to something clearer? Ryan Reich 18:13, 10 October 2007 (UTC)
thread_title:  Terminal substring 

message: In the following text: "As we already know that these characters match the two characters prior to the current position, we need not check them again; we simply reset m = 8, i = 2 and continue matching the current character.", shouldn't it be "m = 10, i = 2"? m[10] and i[2] are the next characters to be compared, so this seems wrong to me. --132.199.235.61 (talk) 19:06, 15 May 2008 (UTC)
replies: text: No.  You don't understand the notation: m is the beginning of the word, and i is the position within the word.  So, we position W so that W[0] = S[8] (that's what m = 8 means) and then start matching at W[2] (which is S[10]). Ryan Reich (talk) 20:47, 15 May 2008 (UTC)
replies: text:  I was confused and came here to ask the same question.  The comment by Ryan Reich explains this perfectly, maybe (some of) his text should be added to that step? --Cloudmonkey (talk) 20:43, 2 January 2019 (UTC)
thread_title:  Error in "working example of ..."? 

message: In the pseudocode for kmp_search, should the line "if T[i] is greater than 0," be "if T[i] is greater than -1,"?  —Preceding unsigned comment added by Byronknoll (talk • contribs) 21:20, 30 November 2009 (UTC)
replies: text: I discussed the pseudocode with two friends and they also agreed it is a mistake. I have corrected it on the main article.--Byron (talk) 06:21, 1 December 2009 (UTC)
thread_title:  Possible Error in Pseudocode 

message: I just inserted a new row above the m:0123... with the numbers 1,2, in order to read that columns of m as 10, 20, vertically.
That change is very minor, it looks correctly aligned in my browser (Mozilla FireFox). 
It should be reverted, i.e. erase the row with 1 2 above m:01234..., if it is not seen aligned in other browsers. — Preceding unsigned comment added by Elias (talk • contribs) 13:36, 22 January 2010 (UTC)
thread_title:  A very minor change, may be not work 

message: Shouldn't the example read:
i   	0 	1	2	3	4	5	6	7	8	9	0	1	2	3	4	5	6	7	8  	9	0	1	2	3
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	0	1	2	0	0	0	0	0	0	1	2	*3*	0	0	0	0	0
Instead of:
i   	0 	1	2	3	4	5	6	7	8	9	0	1	2	3	4	5	6	7	8  	9	0	1	2	3
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	0	1	2	0	0	0	0	0	0	1	2	*0*	0	0	0	0	0
Apologies if I am mistaken. Tony (talk) 16:06, 5 October 2010 (UTC)
thread_title:  Error in the example??? 

message: The article is confusing to read because T is referred to before it is defined in the description of the algorithm in the first section.  —Preceding unsigned comment added by 12.47.208.58 (talk) 00:30, 13 April 2011 (UTC)
replies: text: Agree. Confuses me as well.  — Preceding unsigned comment added by 80.254.148.43 (talk) 09:43, 3 November 2011 (UTC)
replies: text: Yes, this is confusing. Anubhab91 (talk) 15:27, 23 February 2012 (UTC)

text: Also confused at first by this methodology.  It's unclear.  Vote for prioritizing the above suggestion. Dan McCarty (talk) 15:08, 6 September 2012 (UTC)
thread_title:  T used before it is defined 

message: It seems to m that the Algorithms given here are difficult to comprehend. Can anyone please modify the algorithms in simpler forms? Thank you. 
And especially in the explanation of building the T table, it is really obscure to understand the process. As for the pseudocode, the second branch (if cnd > 0, let cnd ← T[cnd]) looks very weird. I hope this part can be better presented with a good example if possible.
Anubhab91 (talk) 15:33, 23 February 2012 (UTC)
replies: text: Do you have any concrete suggestions? Otherwise I'm tempted to point to the story of Euclid and Alexander. I'm sure there are things that could be improved about our description but the main reason that it's difficult to understand is that it's a highly-nontrivial algorithm. —David Eppstein (talk) 05:01, 4 February 2013 (UTC)
thread_title: Difficulty in understanding  Algorithms

message: This part of the explanation--"we note that no 'A' occurs between positions 0 and 3 in S except at 0"--leaves out the step of how we "note" it.  Is it related to the table T[]?  Were we tracking previous starts of the search string?  It's unclear.  Thx.
Dan McCarty (talk) 15:16, 6 September 2012 (UTC)
thread_title: Explanation skips a step

message: 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)
That is silly, the output is T, it is not input. NotYourFathersOldsmobile (talk) 10:45, 20 September 2015 (UTC)
thread_title:  no output, input is output? 

message: In the section partial match the first sentence is:
"The goal of the table is to allow the algorithm not to match any character of S more than once."
However, the Worked example shows that `S[3]` is matched twice: once against `W[3]` and once against `W[0]`.
Who is wrong: the example, that sentence, or me?  — Preceding unsigned comment added by 83.85.105.41 (talk) 11:21, 21 April 2016 (UTC)
replies: text: When W[3] was tested agains S[3], the characters did not match. That is, position S[3] has not matched against anything yet, so the algorithm continues to search for a match at that position. Glrx (talk) 23:49, 23 April 2016 (UTC)
thread_title:  are characters matched more than once? 

message: The following is my python code which run the same example as the original article. However, firstly, the pseudocode in section 2.2 is very different from what described in section 2.1. Secondly, I believe the pseudocode is wrong. If T[i] > -1 and there is a mismatch, then the algorithm will never increase m, thus enters a dead loop.
  if __name__ == '__main__':
    w = 'ABCDABD'
    s = 'ABC ABCDAB ABCDABCDABDE'
    t = [-1,0,0,0,0,1,2]
    m = 0
    i = 0
    while m + i < len(s):
      if w[i] == s[m+i]:
        if i == len(w) - 1:
          print 'found', m
          break
        i += 1
      else:
        if t[i] > -1:
          i = t[i]
        else:
          m += 1
          i = 0
    print 'end'  — Preceding unsigned comment added by Bohu88 (talk • contribs) 03:06, 14 June 2016 (UTC)
thread_title:  I believe the pseudocode is wrong 

message: The value of cnd can become equal to -1, and then W[cnd] becomes meaningless. This happens for example if the word to be analyzed W is "aabaaaa" when we try to compute T[6] using the given algorithm.  — Preceding unsigned comment added by Agostino1984 (talk • contribs) 16:33, 22 August 2016 (UTC)
thread_title:  Mistake in pseudocode for the table-building algorithm 

message: Without mentioning that T can be equal to -1 only for i == 0 (so that m ← m + 1, i ← 0 is executed) the complexity analysis does not make any sense.
When you read Efficiency of the search algorithm section you know nothing about T. So you can assume that i can be set to 0 after every mismatch making the algorithm O(n^2).  — Preceding unsigned comment added by 31.179.124.4 (talk) 21:55, 9 November 2016 (UTC)
thread_title:  Efficiency of the search algorithm 

message: Algorithm seems difficult. Number of versions of this page contain errors.
Current version https://en.wikipedia.org/w/index.php?title=Knuth%E2%80%93Morris%E2%80%93Pratt_algorithm&oldid=781303383 (indexes increment when match, pattern shift when mismatch) differ from presented in many books and internet pages (pattern shift when mismatch, then indexes increment). What version are more simple (especially table-building algorithm)?
Avhohlov (talk) 22:41, 25 May 2017 (UTC)
thread_title:  What algorithm form are easy to understand? 

message: It is seems that difference in action when mismatch occurs. In original paper "Fast pattern matching in strings" (SIAM J. COMPUT. Vol. 6, No. 2, June 1977) by D.Knuth, J.Morris and V.Pratt pattern shifted always, in CLR book version only when match length greater then zero.
So, in CLR book version pattern shift by match length plus one character are impossible.
  algorithm kmp_search: {CLR}
     input:
         an array of characters, S (the text to be searched, all arrays one-based)
         an array of characters, W (the word sought)
 
     define variables:
         an integer, i ← 1 (the position of the current character in S)
         an integer, q ← 0 (match length, not position)
         an array of integers, T (the table, computed elsewhere)
 
     while i <= length(S) do
         while q > 0 and S[i] != W[q + 1] do
             let q ← T[q]
 
         if S[i] = W[q + 1] then
             let q ← q + 1
 
         let i ← i + 1
 
         if q >= length(W) then
             (occurrence found)
             let q ← T[q]
  algorithm kmp_search: {SIAM J. Comput. modified for all occurences search}
     input:
         an array of characters, S (the text to be searched, all arrays one-based)
         an array of characters, W (the word sought)
 
     define variables:
         an integer, k ← 1 (the position of the current character in S)
         an integer, j ← 1 (the position of the current character in W, not length)
         an array of integers, T (the table, computed elsewhere)
 
     while k <= length(S) do
         while j > 0 and S[k] != W[j] do
             let j ← T[j]
 
         let k ← k + 1
         let j ← j + 1
 
         if j > length(W) then
             (occurrence found)
             let j ← T[j]
  algorithm kmp_search: {CLR equivalent}
     input:
         an array of characters, S (the text to be searched, all arrays one-based)
         an array of characters, W (the word sought)
 
     define variables:
         an integer, i ← 1 (the position of the current character in S)
         an integer, q ← 0 (match length, not position)
         an array of integers, T (the table, computed elsewhere)
 
     while i <= length(S) do
         if S[i] = W[q + 1] then
             let i ← i + 1
             let q ← q + 1
 
             if q >= length(W) then
                 (occurrence found)
                 let q ← T[q]
         else
             if q > 0 then
                 let q ← T[q]
             else
                 let i ← i + 1
  algorithm kmp_search: {CLR equivalent, k = q + 1}
     input:
         an array of characters, S (the text to be searched, all arrays one-based)
         an array of characters, W (the word sought)
 
     define variables:
         an integer, i ← 1 (the position of the current character in S)
         an integer, k ← 1 (the position of the current character in W)
         an array of integers, T (the table, computed elsewhere)
 
     while i <= length(S) do
         if S[i] = W[k] then
             let i ← i + 1
             let k ← k + 1
 
             if k > length(W) then
                 (occurrence found)
                 let k ← T[k - 1] + 1
         else
             if k > 1 then
                 let k ← T[k - 1] + 1
             else
                 let i ← i + 1  — Preceding unsigned comment added by Avhohlov (talk • contribs) 22:58, 14 March 2018 (UTC)
thread_title:  Algorithm in "Introduction to Algorithms" book by Cormen, Leiserson, Rivest, Stein differ from original paper? 

message: Not stating where the index m starts or if it's incremented each step or not makes the algorithm very hard to follow. Would love to see this cleaned up a bit so people not familiar with the algorithm would be able to learn it more easily.  — Preceding unsigned comment added by 2605:6000:EC17:D800:8E3:EC21:F3A7:8490 (talk) 17:24, 11 May 2018 (UTC)
thread_title:  Example walkthrough of the algorithm 

message: Someone added 'let j ← j + k - T[k]' to the kmp_search algorithm which breaks it (and the change doesn't really make any sense... I think)
Checkout my tests here that show it's broken that way. Hope that's OK!
https://repl.it/@Craxic/ImprobableSpanishRectangles#main.py — Preceding unsigned comment added by Craxic (talk • contribs) 16:11, 7 June 2020 (UTC)
thread_title:  Mistake in the kmp_search pseudocode... I reverted it.