Help fix my KMP search algorithm
Hello I am trying to write a C# version of KMP search from Algorithms in C book. Having trouble finding the flaw in my algorithm. Would someone help?
static int KMP(string p, string str) {
int m = p.Length;
int n = str.Length;
int i;
int j;
int[] next = new int[m];
next[0] = -1;
for (i = 0, j = -1; i < m; i++, j++, next[i] = j) {
//Getting index out of bounds
while (j > 0 && p[i] != p[j]) j = next[j];
}
for (i = 0, j = 0; i < n &开发者_运维知识库;& j < m; i++, j++) {
while (j >= 0 && p[j] != str[i]) j = next[j];
if (j == m) return i - m;
}
return -1;
}
The simple answer is in the first loop i++ is settling before next[i] = j so on the last character of the search string its trying to set next[m+1] to j - which causes an index out of bounds exception. Try changing the order:
for (i = 0, j = -1; i < m; next[i] = j, i++, j++)
More fundamentally, try breaking the implementation into testable parts. For example, you can extract a testable method for the first loop as it is building the computed table for the search word. Start with:
public int[] BuildTable(string word)
{
// todo
}
and some NUnit tests based on the wiki description
[Test]
public void Should_get_computed_table_0_0_0_0_1_2_given_ABCDABD()
{
const string input = "ABCDABD";
var result = BuildTable(input);
result.Length.ShouldBeEqualTo(input.Length);
result[0].ShouldBeEqualTo(-1);
result[1].ShouldBeEqualTo(0);
result[2].ShouldBeEqualTo(0);
result[3].ShouldBeEqualTo(0);
result[4].ShouldBeEqualTo(0);
result[5].ShouldBeEqualTo(1);
result[6].ShouldBeEqualTo(2);
}
[Test]
public void Should_get_computed_table_0_1_2_3_4_5_given_AAAAAAA()
{
const string input = "AAAAAAA";
var result = BuildTable(input);
result.Length.ShouldBeEqualTo(input.Length);
result[0].ShouldBeEqualTo(-1);
result[1].ShouldBeEqualTo(0);
result[2].ShouldBeEqualTo(1);
result[3].ShouldBeEqualTo(2);
result[4].ShouldBeEqualTo(3);
result[5].ShouldBeEqualTo(4);
result[6].ShouldBeEqualTo(5);
}
Next write one or more tests for the KMP method.
[Test]
public void Should_get_15_given_text_ABC_ABCDAB_ABCDABCDABDE_and_word_ABCDABD()
{
const string text = "ABC ABCDAB ABCDABCDABDE";
const string word = "ABCDABD";
int location = KMP(word, text);
location.ShouldBeEqualTo(15);
}
Then implement using the structure used on the wiki description of the algorithm and it should come together for you.
public int KMP(string word, string textToBeSearched)
{
var table = BuildTable(word);
// rest of algorithm
}
精彩评论