1. 程式人生 > 其它 >KMP子串匹配

KMP子串匹配

using namespace std;
#include <iostream>
#include<string>

//自定義字串儲存結構String(包括char陣列、length長度)
#define maxlen 20
typedef struct {  
    char ch[maxlen];
    int length;
}String;

//初始化s
void strInit(String& s) {
    s.length = 0;
    s.ch[0] = s.length; //ch[0]空著用來存長度,初始化為0
}

//s判空
bool strEmpty(String s) {
    
if (s.length == 0) //如果長度為0代表空串 return true; else return false; } //獲得s長度 int strLength(String s) { cout << "長度列印:" << s.length << endl;; return s.length; //或者s.ch[0] } //將string字串賦值到s資料結構中用char陣列儲存 String strAssign(String &s, string t) { int i = 1; //從1開始存字元,0空著用來存長度
s.length =0; cout << "字串列印:"; for (int j = 0; j < t.length(); j++) { s.ch[i] = t[j]; cout << s.ch[i] << " "; s.length++; i++; } s.ch[0] = s.length; //0空著用來存長度 cout << endl; return s; } /////////上面都是一些基礎函式,下面開始KMP演算法///////////////////////////////////////////// //step1:求出子串的next[j]值【普通版】
void get_next(String s, int next[]) { int j = 1, k = 0; next[1] = 0; //next[1]值必須填0 while(j<s.length){ if (s.ch[j] == s.ch[k] || k == 0) { j++; k++; next[j] = k; } else k = next[k]; } //列印看看 cout <<"列印next[i]為: "; for (int i = 1; i <=s.length; i++) cout << next[i] << " "; cout << endl; } //step1:求出子串的nextval[j]值【改進版,只記錄不相同值的索引,避免j的無效回退。2個方法2選1即可】 void get_nextval(String s, int nextval[]) { int j = 1, k = 0; nextval[1] = 0; //nextval[1]值必須填0 while (j < s.length) { if (s.ch[j] == s.ch[k] || k == 0) { j++; k++; if (s.ch[j] != s.ch[k]) nextval[j] = k; else nextval[j] = nextval[k]; } else k = nextval[k]; } //列印看看 cout << "列印nextval[i]為: "; for (int i = 1; i <= s.length; i++) cout << nextval[i] << " "; cout << endl; } //step2:開始主串中匹配子串,並返回第一個元素出現的位置 int index3(String s, String t, int next[]) { int i = 1, j = 1; while (i <= s.length && j <= t.length) { //找到最後一個字元為止 if (j == 0||s.ch[i] == t.ch[j]) { //如果字元不相同或者j為0了,i和j同步往後移1位 i++; j++; } else j = next[j]; //j回退到next[j]位置 }//while結束,s和t至少有一個找到頭了 if (j > t.length) { //列印看看 cout << "index3列印子串為: "; for (int m = i - t.length; m < i; m++) cout << s.ch[m] << " "; cout << endl; return (i - t.length); //或者i-t.length,返回i最開始的位置 } else return 0; } void main() { int next[20];   int nextval[20];   string sf = "aaaacabcaaaabab";   string sz = "aaaab"; String ss ,tt; strInit(ss); //初始化主串 strInit(tt); //初始化子串 strAssign(ss, sf); //把字串放進資料結構 strAssign(tt, sz); //把字串放進資料結構 strLength(ss); //獲取長度 strLength(tt); //獲取長度 get_next(tt, next); //獲得子串各個next值 cout << "用next的index3 i下標:" << index3(ss, tt, next) << endl; get_nextval(tt, nextval); //獲得子串各個nextval值 cout << "用nextval的index3 i下標:" << index3(ss, tt, nextval) << endl; }