串(String)
逻辑结构:受限线性表
存储结构:
定长顺序存储表示
1 2 3 4 5
| #define Max 255 typedef struct{ char ch[Max]; int length; }SString;
|
堆分配存储表示
1 2 3 4
| typedef struct{ char *ch; int length; }HString;
|
链式存储表示
1 2 3 4 5 6
| #define size 4 typedef struct{ char ch[size]; LString *next; }LString;
|
堆分配存储表示的详解
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36
| #include <stdio.h> #include <stdlib.h> #include <string.h>
typedef struct { char *ch; int length; } HString;
void initHString(HString *str, const char *source) { str->length = strlen(source); str->ch = (char *)malloc((str->length + 1) * sizeof(char)); if (str->ch == NULL) { fprintf(stderr, "Memory allocation failed\n"); exit(1); } strcpy(str->ch, source); }
void freeHString(HString *str) { free(str->ch); str->ch = NULL; str->length = 0; }
int main() { HString myString; initHString(&myString, "Hello, World!");
printf("String: %s\n", myString.ch); printf("Length: %d\n", myString.length);
freeHString(&myString);
return 0; }
|
!(/img/2025_3_16/001.png)
串的简单模式匹配
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
| int SMatch(char a[], char b[]) { char *ptra = a; char *temp = ptra; char *ptrb = b; while (*ptra != '\0') { temp = ptra; ptrb = b; while (*ptra == *ptrb && *ptrb != '\0') { ptra++; ptrb++; } if (*ptrb == '\0') { return 1; } ptra = temp + 1; } return 0; }
int main(void) { char a[] = "ijijij"; char b[] = "ijijij"; printf("%d", Com(a, b)); }
|
简单模式匹配算法的时间复杂度为O(mn)
KMP算法
- 字符串的前缀、后缀与部分匹配值

此方法作为为手算Next数组的方法的理论来源
KMP算法旨在减少主串与辅串回溯的次数,降低算法的时间复杂度。核心是利用匹配失败后的信息。
假设主串S的长度为m,辅串T的长度为n,理论上最坏情况下迭代m-n+1
轮,同时每轮进行n
次比对,一共比较了(m-n+1)*n
次,当m>>n
时,时间复杂度为O(m*n)
。KMP算法可将时间复杂度降低为O(m+n)
。
如何求next数组
next[j] = -1
:j = 0
。表示如果辅串第一个字符不匹配,则主串指针递增,辅串指针不变。
next[j] = x
:x = 最长相等前后缀长度
。为什么要取最长?这样想,若next值尽量的大,则说明前面已经匹配的越多,那么辅串向后移动的位数也越少,如果不取最大值,引发辅串向后移动位数太多,可能会错过匹配的选项。主串指针改变,辅串指针改变。
next[j] = 0
:其他情况
。最坏情况下,从辅串第一个字符开始比较。主串指针不变,辅串指针该变。
代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
| int match (char* P, char* S){ int* next = buildNext(P); int m = (int) strlen (S), i = 0; int n = (int) strlen(P), j = 0; while (j < n && i < m) if (0 > j || S[i] == P[j]) {i++; j++;} else j = next[j]; delete [] next; return i - j; }
int* buildNext(char* P) { size_t m = strlen(P), j = 0; int* N = new int[m]; int t = N[0] = -1; while (j < m - 1) if ( 0 > t || P[j] == P[t]){ j++; t++; N[j] = t; }else t = N[t]; return N;
}
|
参考文献
leetcode关于KMP的图片粗略解释
王道计算机考研2025版本