子串:字串中任一連續的片段,稱作其子串(substring)
字首:prefix(s, k) = s.substr(0, k) = s[0, k)
字尾:suffix(s, k) = s.sbustr(n-k, k) = s[n-k, n)
串模式匹配(string pattern matching):
對基於同一字元表的任何文字t(|t| = n)和模式串p(|p| = m):
- 判定t中是否存在某一子串與p相等
- 若存在(匹配),則報告該字串在t串的起始位置
演算法1:
int match(char* p, char* t)
else
}return i - j; //當(i-j)>m時,發現匹配,且p相對於t的對齊位置為i-j
}
演算法2:int match(char* p, char* t)
n(p, j) = \
n(p,j)
=一般地,該集合可能包含多個這樣的t,但需要注意的是,其中具體有哪些t構成,僅取決於模式串p以及前一輪比對的首個失配位置p[j],與文字串t無關。
int kmp(char* p, char* t)
else
j = next[j];
} delete next;
return i - j;
}
與蠻力演算法1相比,僅失配時演算法有所區別:kmp演算法此時保持i不變,從next表中取出乙個j來代替置零。注意if判斷條件多了乙個0可以看到,我們統一將n[0]賦值為-1,此處可假定在p[0]前面有乙個哨兵,該哨兵是乙個萬用字元,遇其必然進入if分支,該處相當於整個p在t[i]都沒有匹配的位置,因此要將p移動|p|步,並將i向右移動1步,即:
因此可以解釋為何kmp演算法中if判斷條件為何多了乙個。至此,我們簡單分析完了kmp演算法的策略與演算法實現,在buildnext**中,我們可以進一步優化,可改寫其為:
n[j] = (p[j] != p[t] ? t : n[t]);
其原因與正確性暫且不表。
我們僅需將目光放在演算法的迴圈部分:
while (i < n && j < m)
else
j = next[j];
}
引入k = 2*i - j,對於if分支,i、j必然同時+1,則k必然會+1;對於else分支,i不變,next[j]必然至少會比j小1,則k至少也+1因此,k具有單調遞增的特性。再考慮最後k的範圍,其初始值為0,迴圈結束後有:
k =2
∗i−j
≤2∗(
n−1)
−(−1
)=2n
−1k = 2*i - j ≤ 2*(n-1) - (-1) = 2n - 1
k=2∗i−
j≤2∗
(n−1
)−(−
1)=2
n−1則得出結論,k單調遞增,且最大至o(n);算上buildnext所需要的時間,則kmp演算法時間複雜度為o(n+m)。
bm演算法中依然是將模式串p與文字串t從左開始對齊,但是卻是自模式串的右邊向左邊進行掃瞄對比。為實現高效率,bm演算法同樣是充分利用以往的資訊,使得p可以「安全的」往後盡可能多的移動。
int bm(char* p, char* t)
delete gs;
delete bc;
if (i + strlen(p) <= strlen(t))
return i;
else
return -1;
}
bm演算法通過提前計算壞字元與好字尾的情況,從而在遇到時進行盡可能多的移動。
int* buildbc(char* p)
int* buildgs(char* p)
} for (size_t j = 0; j < m - 1; ++j)
gs[m - ss[j] - 1] = m - j - 1;
delete ss;
return gs;
}int* buildss(char* p)
} return ss;
}
如下圖,得出以上幾種演算法的效能分析。
蠻力演算法字串匹配
在這裡我們運用蠻力演算法解決,另外此問題還能用kmp演算法。該演算法的做法是將模式 也就是較短的子串,長度為m 對準文字 也就是較長的字串,長度為n 的前m個字元,從左到右匹配每一對相應的字元,如果有m對字元都匹配成功,那麼演算法停止,或者當遇到有一對不匹配時就將模式向右移一位,然後繼續從模式的第乙...
字串匹配 蠻力 KMP
前兩篇文章是從網上搜尋的,知道了next陣列可以有多種表示方法,但感覺kmp演算法詳解裡面第二種表示法給的程式有點小問題,今天自己改進了下,然後在leetcode strstr 上驗證了下,發現自己改進的程式可以ac,證明沒有問題 現在在這篇部落格中總結蠻力 kmp bm演算法的各種ac解法 蠻力法...
字元字串模式匹配演算法 BF演算法與KMP演算法
需解決的問題 從主字串s中尋找子字串t出現的第乙個位置?如果出現,返回pos,否則,返回 1 一 bf演算法 bf演算法就是樸素模式匹配演算法,即暴力求解,迴圈遍歷。將子字串的每個字元和主字串的字元按順序比較,如果比較不相等時,兩個字串的索引i和j同時回退,i回退到剛才主字串起始位置的下一位,子字串...