給定主串 haystack(長度 n)與模式串 needle(長度 m),找出 needle 在 haystack 中首次出現的起始位址;若不存在返回 NULL。這是 C 標準庫 strstr 的核心功能。
NULL 直接返回 NULL。n < m 必無解。i 從 0 掃描至 n-m。i,檢查 haystack[i+j] == needle[j] 對所有 j ∈ [0, m) 是否成立。i。j == m),返回 haystack + i。NULL。
#include
#include
char* strstr_bruteforce(const char *haystack, const char *needle) {
if (!haystack || !needle) return NULL;
size_t n = strlen(haystack);
size_t m = strlen(needle);
if (m == 0) return (char*)haystack; // 空模式串匹配開頭
if (n < m) return NULL;
for (size_t i = 0; i <= n - m; ++i) {
size_t j = 0;
for (; j < m; ++j) {
if (haystack[i + j] != needle[j]) break;
}
if (j == m) return (char*)(haystack + i);
}
return NULL;
}
| 指標 | 數值 | 說明 |
|---|---|---|
| 最好時間 | O(m) | 首位即匹配,或首字元即失配且模式串極短 |
| 最壞時間 | O(n·m) | 如 haystack="aaaa...a", needle="aaa...ab",每次比對 m-1 字元後失配 |
| 平均時間 | O(n+m) | 隨機字串下期望線性 |
| 空間複雜度 | O(1) | 僅常數額外變數 |
| 錯誤代碼 | 問題 | 修正 |
|---|---|---|
while(*s && strlen(s) >= m) | 每輪呼叫 strlen 導致 O(n²) | 預先計算 n, m,迴圈上界固定 |
if (NULL == str || NULL == str) | 重複檢查 str,漏檢 data | if (!haystack || !needle) |
未處理 m == 0 | 標準規定空模式串匹配開頭 | 開頭判斷 if (m == 0) return (char*)haystack; |
外層上界寫 i < n | 越界讀取 haystack[i+j] | i <= n - m(注意 size_t 無號減法下溢) |
#include
void test_strstr(void) {
assert(strstr_bruteforce(NULL, "abc") == NULL);
assert(strstr_bruteforce("abc", NULL) == NULL);
assert(strstr_bruteforce("", "abc") == NULL);
assert(strstr_bruteforce("abc", "") == (char*)"abc");
assert(strstr_bruteforce("hello world", "world") == (char*)"hello world" + 6);
assert(strstr_bruteforce("aaaaa", "aa") == (char*)"aaaaa");
assert(strstr_bruteforce("abc", "abcd") == NULL);
assert(strstr_bruteforce("mississippi", "issip") == (char*)"mississippi" + 4);
}
暴力法在最壞情況下效能不可接受。下一步優化思路:
strlen)。暴力比對法雖簡單,但包含「邊界處理、雙層迴圈、提前剪枝、指標運算」等系統程式設計核心技能。熟練寫出無 Bug 版本,是進階學習 KMP、BM、AC 自動機等高階字串演算法的基石。工程上:除非極度受限環境,否則優先使用標準庫 strstr;面試中:能手寫正確暴力版、說清複雜度、指出優化方向即達標。