字串匹配

2022-05-03 11:09:26 字數 4014 閱讀 5440

字串匹配

時間複雜度o(m*n),普通的模式匹配演算法

bf演算法的思想就是將目標串s的第乙個字元與模式串t的第乙個字元進行匹配,若相等,則繼續比較s的第二個字元和 t的第二個字元;

若不相等,則比較s的第二個字元和t的第乙個字元,依次比較下去,直到得出最後的匹配結果。bf演算法是一種蠻力演算法。

輸出s2在s1裡出現的次數

我寫的,兩行獲取兩行字元,第二行的字串在第一行的字串匹配,看看有幾個

#include #include #include using namespace std;

const int maxn = 1e6 + 5;

int main()else

}if(flag)cnt++;}}

printf("%d\n",cnt);

return 0;

}

匹配成功,繼續,匹配失敗回溯

輸出第一次匹配的下標

#include #include using namespace std;

int bf(char a, char b)else

}if(j == len2) return index + 1;//匹配成功

else return 0;

}int main()

時間複雜度o(m+n)

對於樸素演算法的乙個缺點就是每次子串匹配失敗就會回溯,所以kmp針對這個問題,使得主串不需要回溯,只對子串進行回溯

而next就解決了這個問題,如果說主串和子串進行匹配,而在主串i與子串j位置失配,那麼i前面和j前面那一段必定是匹配的,那麼也就是說,可以採用回溯子串使得子串中與其前面具有相同結構部分進行回溯

字首:指的是字串的子串中從原串最前面開始的子串,如abcdef的字首有:a,ab,abc,abcd,abcde

字尾:指的是字串的子串中在原串結尾處結尾的子串,如abcdef的字尾有:f,ef,def,cdef,bcdef

注意,字首與字尾均不包含本身

kmp演算法最大的特點是加入了next[i]陣列

next[i]的含義是對於字串去掉下標為i的字元後的字串的字首與字尾的最長匹配

這是普遍的定義

求解next

**next求解

下面是基於清華資料結構教材的定義去求我絕對不是為了考試才這麼去解釋的也就是字串下標以0位開頭的

比如求ababa的next值i字元

去掉i之後的字元

字首字尾

next0a

null

null

null-11

abanull

null02

abaabab

03abab

abaabba1

4ababa

abab

ababab

2

考研題庫裡面求出來的值是該方法求出的值加1,因為初始下標的定義不同,next[i]是進行匹配的,所以如果字串從1開始,那就把next值加1,而字串從0開始,就按照上面去求即可

void getnext()else}}

主要i和j的起始位置即可,本文都是以下標0開始

當子串重複個數很多的時候,子串的回溯很浪費時間,所以加入了新的優化

比如aaaaaaaa進行匹配時,當最後乙個a匹配失敗,就會乙個乙個地向前回溯,很浪費時間,如果最後乙個a的next直接指到第乙個a就好了

那麼在求next時加乙個判斷

if(t[i] == t[j])next[i] = next[j];
void getnext()else}}

如何手動求

只要在求得next之後,再遍歷一下,看t[i]和t[next[i]]是否相同,相同的話就把t[i]的next改了,next[i] = next[next[i]];

主要在於j的回溯

int kmp()else j = next[j];

}return i - len2;

}

傳送門

輸出匹配的首字母下標和next陣列

#include #include #include using namespace std;

char a[1000005];

char b[1000005];

int next[1000005];

int len1, len2;

void getnext()

if(b[p + 1] == b[i])p++;

next[i] = p;

}}void kmp()

}for(int i = 1; i <= len2; i++)

printf("%d ",next[i]);

}int main()

另一種寫法

#include #include #include #include #include const int maxn = 1e6+5;

using namespace std;

int next[maxn];

char s[maxn];

char t[maxn];

int len1, len2;

void kmp()else

if(j == len2)

}}void getnext()else

}}void print()

}int main()

傳送門

#include #include #include using namespace std;

char a[1000005];

char b[1000005];

int next[1000005];

int len1, len2;

int cnt;

void getnext()

if(b[p + 1] == b[i])p++;

next[i] = p;

}}void kmp()

}}int main()

return 0;

}

傳送門

#include #include #include using namespace std;

int a[1000005];

int b[1000005];

int next[1000005];

int len1, len2;

int cnt;

int flag = -1;

void getnext()

if(b[p + 1] == b[i])p++;

next[i] = p;

}}void kmp()

}}int main()

for(int j = 1; j <= m; j++)

len1 = n;

len2 = m;

getnext();

kmp();

printf("%d\n", flag == -1 ? -1 : flag);

}return 0;

}

字串匹配

題目描述 讀入資料string 然後讀入乙個短字串。要求查詢string 中和短字串的所有匹配,輸出行號 匹配字串。匹配時不區分大小寫,並且可以有乙個用中括號表示的模式匹配。如 aa 123 bb 就是說aa1bb aa2bb aa3bb都算匹配。輸入 輸入有多組資料。每組資料第一行輸入n 1 n ...

字串匹配

time limit 1000ms memory limit 65536k 給定兩個字串string1和string2,判斷string2是否為string1的子串。輸入包含多組資料,每組測試資料報含兩行,第一行代表string1,第二行代表string2,string1和string2中保證不出現...

字串匹配

面試題 給一串很長的字串,要求找到符合要求的字串,例如目的串 123 1 3 2 12 3 這些都要找出來 思路一 利用兩層迴圈,逐個查詢目的串中的字元,比如先查詢字元 1 是否在長字串中,再查詢 2 是否在長字串中,直到目的串遇到 0 是 include include include int m...