#ifndef _kmp_
#define _kmp_
#include #include using namespace std;
void testkmp();
int match1(const string &target, const string &pattern);
/* 根據事先的資訊,在失配時,直接移動到相應位置
*//*
kmp:不好理解的地方
1.覆蓋函式的求取
如果不相等,把它認為是一次錯誤匹配,因此k=next[k]
覆蓋函式:表示pattern自身的性質
*/// 計算覆蓋值
void calculatenext(string pattern, int next, int size);
// kmp演算法
int kmpmatch(const string& target, const string& pattern);
void printnext(int next, int size);
/* 字串匹配:bm演算法
*/// 從後往前匹配
int match2(const string &target, const string &pattern);
/* 對於在pattern中沒有的字元,直接跳過
如果有:從後往前找到第乙個出現的位置
*/// 建立字元表
void buildbadcharhash(const string &pattern, int hash, int size);
int match3(const string &target, const string &pattern);
/* bm:尋找乙個位置,讓已匹配的字尾與模式串中從後往前最近的乙個相同的子串對齊
類似於:next
只不過是從後往前看,其實是一樣的
找到已匹配的字元的最長字首
可否用遞推?
考慮到好字首之後...
現在的關鍵問題是:
*/// 好好理解
void suffixes(char *x, int m, int *suff);
/* skip(x) = (len);x在pattern中未出現
m-max(x):x在pattern中出現的最大位置
*/// 這個skip上面已經計算過
/* good suffix
如果已匹配的字首在pattern中沒有出現,
找到最長的字尾
*/void goodsuffix(const string &pattern, int *suffix, int size);
int bmmatch(const string& target, const string& pattern);
#endif
#include #include "4_kmp.h"
void testkmp()
// 樸素匹配:只是找到第乙個匹配項
int match1(const string &target, const string &pattern)
else // patternindex需要置0 targetindex需要向左移動多少?
} // 找到乙個匹配項
if (patternindex == patternlen)
return -1;
}void calculatenext(string pattern, int next, int size)
// 跳出迴圈:1.j == -1 2.pattern[j + 1] == pattern[i]
next[i] = j + 1;
// 排除=-1的情況
if (pattern[j + 1] != pattern[i])
}}int kmpmatch(const string& target, const string& pattern)
else if (pindex == 0)
else // 匹配模式:比較的是前面的匹配情況,因此這裡用next[pindex - 1]
} if (pindex == plen)
return -1;
}void printnext(int next, int size)
cout << endl;
}int match2(const string &target, const string &pattern)
} tindex += (plen - pindex);
pindex = plen - 1;
} return -1;
}// size為256
void buildbadcharhash(const string &pattern, int hash, int size)
for (int i = plen; i >= 0; --i) }
}int match3(const string &target, const string &pattern)
} char c = target.at(tindex);
int tmp = hash[c];
// 設定更長的乙個
tindex += (tmp > (plen - pindex) ? tmp : (plen - pindex));
pindex = plen - 1;
} return - 1;
}void suffixes(char *x, int m, int *suff)
}
} // 這是樸素的演算法!!!
void goodsuffix(const string &pattern, int *suffix, int size)
// 找到乙個匹配串
if (cur + j > m)
cur++;
} }}int bmmatch(const string& target, const string& pattern)
} char c = target.at(tindex);
int badchar = hash[c];
// 好字首
int goodsuffix = suffix[pindex];
// 設定更長的乙個
// 壞字元
int badcharshift = badchar > (plen - pindex) ? badchar : (plen - pindex);
tindex += (goodsuffix > badcharshift ? goodsuffix : badcharshift);
pindex = plen - 1;
} return -1;
}
理解kmp,關鍵是理解pattern的處理,即求取pattern中每乙個字元的最長字首匹配。因此在失配的時候,直接通過找到其前面乙個字母的最長字首匹配,就能定位到下一次要開始匹配的位置。 演算法 KMP演算法
kmp演算法主要解決的問題就是在字串 主串 中的模式 pattern 定位問題。記主串為t,模式串為p,則kmp演算法就是返回p在t 現的具體位置,如果沒有出現則返回 1。如果 i 指標指向的字元和 j 指標指向的字元不一致,那麼把 i 右移1位,j 從0位開始,從新開始匹配 如果 i 指標指向的字...
kmp演算法next例題 KMP演算法next陣列求解
kmp演算法與bf演算法的比較 bf演算法的想法十分樸素,即先將子串t的第一位與主串s的第一位對齊開始匹配,當不能匹配時將子串整體往後移一位,然後重新匹配,以此類推直至排出結果 如當遇到下圖所示情況時,需將子串整體後移一位,將i,j分別回溯到主串第2位和子串第一位。kmp演算法 對bf進行思考後,我...
KMP及KMP改進演算法
kmp 看毛片 演算法確實很難理解,上網搜了半天想了很久才大概想明白。kmp演算法精華在於next陣列 部分匹配值 即next陣列就是 字首 和 字尾 的最長的共有元素的長度。以 abcdabd 為例,a 的字首和字尾都為空集,共有元素的長度為0 ab 的字首為 a 字尾為 b 共有元素的長度為0 ...