开始设计
This commit is contained in:
@@ -0,0 +1,76 @@
|
||||
#include <c_StrIndexKmp.h>
|
||||
#include <c_Memory.h>
|
||||
|
||||
#define MAX_STACK_LPS 128
|
||||
|
||||
static void compute_LPS_table(const char* pattern, c_size_t m, long long* lps) {
|
||||
c_size_t len = 0; // Length of the previous longest prefix suffix
|
||||
lps[0] = 0; // lps[0] is always 0
|
||||
c_size_t i = 1;
|
||||
|
||||
while (i < m) {
|
||||
if (pattern[i] == pattern[len]) {
|
||||
len++;
|
||||
lps[i] = (long long)len;
|
||||
i++;
|
||||
} else {
|
||||
if (len != 0) {
|
||||
len = (c_size_t)lps[len - 1]; // Backtrack without shifting 'i'
|
||||
} else {
|
||||
lps[i] = 0;
|
||||
i++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
long long c_StrIndexKmp(const char* text, const char* pattern) {
|
||||
if (!text || !pattern) return -1;
|
||||
|
||||
const c_size_t n = strlen(text);
|
||||
const c_size_t m = strlen(pattern);
|
||||
|
||||
if (m == 0) return 0; // An empty pattern matches at the very beginning
|
||||
if (m > n) return -1; // Pattern is longer than the text container
|
||||
|
||||
// Optimization: Use a stack buffer if the pattern length fits, avoiding heap allocation cycles
|
||||
long long stack_lps[MAX_STACK_LPS];
|
||||
long long* lps = (m <= MAX_STACK_LPS) ? stack_lps : (long long*)C_ALLOC(m * sizeof(long long));
|
||||
if (!lps) return -1; // Allocation failure fallback
|
||||
|
||||
// Step 1: Precompute the lookup table
|
||||
compute_LPS_table(pattern, m, lps);
|
||||
|
||||
// Step 2: Linear string matching phase
|
||||
c_size_t i = 0; // Index for text
|
||||
c_size_t j = 0; // Index for pattern
|
||||
long long matched_index = -1;
|
||||
|
||||
while (i < n) {
|
||||
if (pattern[j] == text[i]) {
|
||||
i++;
|
||||
j++;
|
||||
}
|
||||
|
||||
if (j == m) {
|
||||
matched_index = (long long)(i - j); // Found match at index (i - j)
|
||||
break; // Terminate early for the first occurrence
|
||||
}
|
||||
// Mismatch after j matches
|
||||
else if (i < n && pattern[j] != text[i]) {
|
||||
if (j != 0) {
|
||||
j = (size_t)lps[j - 1]; // Slide the pattern using the precomputed LPS table
|
||||
} else {
|
||||
i++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Clean up heap memory if it was allocated
|
||||
if (lps != stack_lps) {
|
||||
C_FREE(lps);
|
||||
}
|
||||
|
||||
return matched_index;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user