Improper Output
The algorithm on the page you linked to reads:
algorithm kmp_table:
input:
an array of characters, W (the word to be analyzed)
output:
an array of integers, T (the table to be filled)
define variables:
an integer, pos ← 1 (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)
let T[0] ← -1
while pos < length(W) do
if W[pos] = W[cnd] then
let T[pos] ← T[cnd]
else
let T[pos] ← cnd
while cnd ≥ 0 and W[pos] ≠ W[cnd] do
let cnd ← T[cnd]
let pos ← pos + 1, cnd ← cnd + 1
let T[pos] ← cnd (only needed when all word occurrences are searched)
First thing to check is whether the algorithm is uses 0-based or 1-based arrays. Since it assigns to T[0]
we can immediately tell it is zero based.
Since pos
is being incremented by 1, the while pos < length(W)
loop will end when pos == length(W)
.
The final statement of the algorithm assigns T[pos]
a value. But if pos = length(W)
, this means that the T
array will contain length(W) + 1
elements!
Since you initialize tab = [0] * len(listB)
, the output cannot contain the final value the algorithm should produce! The output table is supposed to be 1 element longer than the input! Using the example from the article, W = “ABCDABD”
(7 letters) is supposed to produce [-1, 0, 0, 0, -1, 0, 2, 0]
(8 elements)
Improper looping
The for i in range(…)
loop does not allow you to advance the loop index. On each iteration, the next value from the range(…)
will be used regardless of any modification made to i
inside the loop. For example:
for i in range(10):
if i == 2:
i = 8
print(i)
will print ten numbers: 0, 1, 8, 3, 4, 5, 6, 7, 8, and 9. After modifying i
, the next iteration continues with i=3
, and does not skip directly to i=9
. For this reason, attempting to modify a for
loop index is confusing to the reader, and should be avoided.
If you want to modify loop indexes manually, use a while
loop, not a for loop.