char *strstr(const char *haystack, const char *needle):在主串 `haystack` 中查找子串 `needle` 首次出現位置,返回該位置指針;未找到返回 `NULL`。
#include <stdio.h>
const char *my_strstr(const char *str, const char *sub_str) {
for (int i = 0; str[i] != '\0'; i++) {
int start = i; // 記錄當前嘗試的起始位置
int j = 0;
// 逐字符比對
while (str[i] == sub_str[j] && sub_str[j] != '\0') {
i++; j++;
}
if (sub_str[j] == '\0') { // 子串完全匹配
return &str[start];
}
i = start; // 回溯:主串指針回到起始位置,外層 for 會 i++
}
return NULL;
}
int main() {
char *s = "1233345hello";
char *sub = "345";
printf("%s\n", my_strstr(s, sub)); // 輸出: 345hello
return 0;
}
主串: 1 2 3 3 3 4 5 h e l l o
↑ ↑
i=2 找到 "345" 起始位置
子串: 3 4 5
↑ ↑ ↑
j=0 1 2 匹配成功,返回 &str[2]
暴力匹配的缺點是主串指針回溯。KMP 通過預處理子串構建next 數組(部分匹配表),實現主串指針不回溯,時間複雜度穩定 O(m+n)。
// 構建 next 數組
void build_next(const char *pat, int *next, int m) {
next[0] = -1;
int k = -1, j = 0;
while (j < m - 1) {
if (k == -1 || pat[j] == pat[k]) next[++j] = ++k;
else k = next[k];
}
}
// KMP 查找
const char *kmp_strstr(const char *txt, const char *pat) {
int n = strlen(txt), m = strlen(pat);
int *next = malloc(m * sizeof(int));
build_next(pat, next, m);
int i = 0, j = 0;
while (i < n && j < m) {
if (j == -1 || txt[i] == pat[j]) { i++; j++; }
else j = next[j];
}
free(next);
return (j == m) ? &txt[i - m] : NULL;
}
本文實現了教學級的暴力模式匹配,代碼簡潔、邏輯清晰,適合理解「雙指針回溯」基本思想。工程生產環境請直接使用標準庫 `strstr`(高度優化、經過充分測試),或在特定場景(如嵌入式無標準庫)考慮 KMP 等線性算法。