C # Generic KMP Algorithm

Source: Internet
Author: User

# Region KMP generic

Private Static int [] Next (ilist <t> pattern)
{
Int [] Next = new int [pattern. Count];
Next [0] =-1;
If (pattern. Count <2) // It is more efficient if only one element does not use KMP.
{
Return next;
}

Next [1] = 0; // The backtracking function value of the second element must be 0, which proves that:
// The pre-sequence set of 1 is {empty set, L [0]}, and the length of L [0] is not less than 1, so it is eliminated. The length of the empty set is 0, therefore, the value of the Backtracking function is 0.
Int I = 2; // the index of the character whose next value is being calculated
Int J = 0; // The intermediate variable required to calculate the next value. At the beginning of each iteration, J is always next [I-1].
While (I <pattern. Count) // it is obvious that when I = pattern. length, the next value of all characters has been calculated and the task has been completed.
{// Status
// Use equals as the element matching condition
If (pattern [I-1]. Equals (pattern [J]) // you must first remember that in the implementation of this function, the next value of iterative calculation starts from the third element.
{// If l [I-1] is equal to L [J], next [I] = J + 1
Next [I ++] = ++ J;
}
Else
{// If not equal, check the next possible value of next [I] ---- next [J]
J = next [J];
If (j =-1) // If J =-1, the value of next [I] is 1.
{// This part can be extracted and combined with the outer judgment
// The KMP in the book Code A difficult reason to understand is that it has been optimized to obscure its actual logic.
Next [I ++] = ++ J;
}
}
}
Return next;

}

Public static int executekmp (ienumerable <t> source, ilist <t> pattern)
{
Int [] Next = next (pattern );
Return executekmpinternal (source, pattern, next );
}

Private Static int executekmpinternal (ienumerable <t> source, ilist <t> pattern, int [] Next)
{
Ienumerator <t> iterator = source. getenumerator ();

Int I = iterator. movenext ()? 0:-1; // the two statements must always be executed together. // The master string pointer

Int J = 0; // mode string pointer
// If the child string does not match and the master string does not search
While (j <pattern. Count & I>-1)
{
If (iterator. current. equals (pattern [J]) // The logical meaning of I and j is embodied in this, used to indicate whether to determine whether the primary and mode strings are equal in this iteration
{
I = iterator. movenext ()? I + 1:-1;
J ++;
}
Else
{
J = next [J]; // iterative Backtracking Based on the indication
If (j =-1) // There is a situation with backtracing. This is the second case.
{
I = iterator. movenext ()? I + 1:-1;
J ++;
}
}
}
// If J = pattern. length, it indicates that the loop exit is because the child string has been matched but not the master string has been exhausted.
Return j <pattern. Count? -1: I-J;
}

/// <Summary>
/// The next function of the generic version
/// </Summary>
/// <Param name = "pattern"> A pattern string can be an object that implements ilist. All arrays implement ilist. </param>
/// <Param name = "isequal"> This function must reflect an equivalent relation, that is, it must meet the requirements of self-inversion, transfer, and exchange. Otherwise Algorithm A logical error occurs. This is the premise of the KMP algorithm. </Param>
/// <Returns> returns the next backtracking function </returns>
Private Static int [] Next (ilist <t> pattern, func <t, t, bool> isequal)
{
Int [] Next = new int [pattern. Count];
Next [0] =-1;
If (pattern. Count <2) // It is more efficient if only one element does not use KMP.
{
Return next;
}

Next [1] = 0; // The backtracking function value of the second element must be 0, which proves that:
// The pre-sequence set of 1 is {empty set, L [0]}, and the length of L [0] is not less than 1, so it is eliminated. The length of the empty set is 0, therefore, the value of the Backtracking function is 0.
Int I = 2; // the index of the character whose next value is being calculated
Int J = 0; // The intermediate variable required to calculate the next value. At the beginning of each iteration, J is always next [I-1].
While (I <pattern. Count) // it is obvious that when I = pattern. length, the next value of all characters has been calculated and the task has been completed.
{// Status
// Use equals as the element matching condition
If (isequal (pattern [I-1], pattern [J]) // you must first remember that in the implementation of this function, the next value of iterative calculation starts from the third element.
{// If l [I-1] is equal to L [J], next [I] = J + 1
Next [I ++] = ++ J;
}
Else
{// If not equal, check the next possible value of next [I] ---- next [J]
J = next [J];
If (j =-1) // If J =-1, the value of next [I] is 1.
{// This part can be extracted and combined with the outer judgment
// One of the reasons why KMP code in the book is hard to understand is that it has been optimized to obscure its actual logic.
Next [I ++] = ++ J;
}
}
}
Return next;

}

Public static int executekmp (ienumerable <t> source, ilist <t> pattern, func <t, t, bool> isequal)
{
Int [] Next = next (pattern, isequal );
Return executekmpinternal (source, pattern, isequal, next );
}

Private Static int executekmpinternal (ienumerable <t> source, ilist <t> pattern, func <t, t, bool> isequal, int [] Next)
{
Ienumerator <t> iterator = source. getenumerator ();

Int I = iterator. movenext ()? 0:-1; // the two statements must always be executed together. // The master string pointer

Int J = 0; // mode string pointer
// If the child string does not match and the master string does not search
While (j <pattern. Count & I>-1)
{
If (isequal (iterator. current, pattern [J]) // The logic meaning of I and j is embodied in this, used to indicate whether to determine whether the primary and mode strings are equal in this iteration
{
I = iterator. movenext ()? I + 1:-1;

J ++;
}
Else
{
J = next [J]; // iterative Backtracking Based on the indication
If (j =-1) // There is a situation with backtracing. This is the second case.
{
I = iterator. movenext ()? I + 1:-1;
J ++;
}
}
}
// If J = pattern. length, it indicates that the loop exit is because the child string has been matched but not the master string has been exhausted.
Return j <pattern. Count? -1: I-J;
}

Private Static int [] nextval (ilist <t> pattern)
{
Int [] Next = new int [pattern. Count];
Next [0] =-1;
If (pattern. Count <2) // It is more efficient if only one element does not use KMP.
{
Return next;
}

Next [1] = 0; // The backtracking function value of the second element must be 0, which proves that:
// The pre-sequence set of 1 is {empty set, L [0]}, and the length of L [0] is not less than 1, so it is eliminated. The length of the empty set is 0, therefore, the value of the Backtracking function is 0.
Int I = 2; // the index of the character whose next value is being calculated
Int J = 0; // The intermediate variable required to calculate the next value. At the beginning of each iteration, J is always next [I-1].
While (I <pattern. Count) // it is obvious that when I = pattern. length, the next value of all characters has been calculated and the task has been completed.
{// Status
// Use equals as the element matching condition
If (j =-1 | pattern [I-1]. equals (pattern [J]) // you must first remember that in this function implementation, the next value of iterative calculation starts from the third element.
{// If l [I-1] is equal to L [J], next [I] = J + 1
J ++;
If (pattern [I]. Equals (pattern [J])
{
Next [I] = next [J];
}
Else
{
Next [I] = J;
}
I ++;
}
Else
{// If not equal, check the next possible value of next [I] ---- next [J]
J = next [J];
}
}
Return next;
}

Public static int executekmpp (ienumerable <t> source, ilist <t> pattern)
{
Int [] Next = nextval (pattern );
Return executekmpinternal (source, pattern, next );
}

# Endregion

The test just now seems to be okay.

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.