樸素的模式比對算法
其實就是一個一個往下比對,沒有任何優化,在好的情況下時間複雜度為O(n+m),在最求的情況下時間複雜度為O((n-m+1)*m)。
代碼實作:
//在主串s中找子串t,若找到傳回字串在主串中的索引;若沒找到傳回-1
#include <iostream>
#include <string>
using namespace std;
int Index(string s, string t){
int lens = s.length();//計算串s、t的長度
int lent = t.length();
int i = ;
int j = ;
while (i < lens&&j < lent){//如果i、j都各自小于lens和lent
if (t[j] == s[i]){//如果子串的t[j]和主串的s[i]相等
++i;//各自索引都自增
++j;
}
else{//否則,主串的索引比剛開始後移一個;子串的索引變為0
i = i - j + ;
j = ;
}
}
if (j == lent){//如果最j和lent的大小一樣,證明找到了,傳回子串在主串中的索引
return i - lent;
}
else{//否則傳回-1
return -;
}
}
int main(){
string s = "goodgoogle";
string t = "google";
int pos = Index(s, t);
if (pos != -){
cout << "find " << t << " at the index " << pos << " of " << s << endl;
}
else{
cout << "can't find " << t << " in " << s << endl;
}
return ;
}
KMP模式比對算法
先對子串t進行next判斷,得到一個next數組,再進行比較。時間複雜度為O(n+m)
代碼實作:
//在主串s中找子串t,若找到傳回字串在主串中的索引;若沒找到傳回-1
#include <iostream>
#include <string>
using namespace std;
void get_next(string t, int *next);
int Index_KMP(string s, string t);
int main(){
string s = "ababadeababaaabadf";
string t = "ababaaaba";
int pos = Index_KMP(s, t);
if (pos != -){
cout << "find " << t << " at the index " << pos << " of " << s << endl;
}
else{
cout << "can't find " << t << " in " << s << endl;
}
return ;
}
int Index_KMP(string s, string t){
int lens = s.length();
int lent = t.length();
int *next = new int[lent];
get_next(t, next); //對子串t作分析,得到next數組
//cout << "next: "; //輸出next測試而已
//for (int i = 0; i < lent; ++i){
// cout << next[i];
//}
//cout << endl;
int i = ;
int j = ;
while (i < lens&&j < lent){//兩字母相等則繼續,與樸素算法增加了j==0的判斷
if (j == || t[j] == s[i]){
++i;
++j;
}
else{
j = next[j-];//j退回合适位置,i值不變
}
}
if (j == lent){//如果最j和lent的大小一樣,證明找到了,傳回子串在主串中的索引
return i - lent;
}
else{//否則傳回-1
return -;
}
}
void get_next(string t, int *next){
int lent = t.length();
int i = ;
int j = ;
next[] = ;
while (i < lent){//i小于t的長度
if (j == || t[i] == t[j - ]){//t[i]表示字尾的單個字元
++i; //t[j]表示字首的單個字元
++j;
next[i] = j;
}
else{
j = next[j - ]; //若字元不相同,則j值回溯
}
}
}