(四)KMP演算法

2021-06-14 11:36:38 字數 3474 閱讀 4191

#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 ...