BF算法(暴力法)
不多解释,直接上代码:
// BF算法 O(mn)
int bf(SString s, SString t, int pos){
int i = pos, j = 0;
while (i < s.length && j < t.length){
if (s.ch[i] == t.ch[j]){
i++;
j++;
} else {
i = i - j + 1;
j = 0;
}
}
if (j >= t.length)
return i - t.length;
else
return -1;
}
// 另一个版本的BF算法 - O(mn)
int pm(SString s, SString t, int pos){
for (int i = pos; i <= s.length-t.length; i++){
bool status = true;
for (int j = 0; j < t.length; j++){
if (s.ch[i+j] != t.ch[j]){
status = false;
break;
}
}
if (status)
return i;
}
return -1;
}
KMP算法
KMP算法较难理解,在大二上数据结构这门课的时候就没有搞懂,今天花了点时间终于把它看懂了。
KMP算法相比BF算法,其改进主要在使用了一个前后缀匹配数组next
(我自己起的名儿~)来记录前缀和后缀的匹配信息,以使得在发现主串与模式串的比较中出现不匹配时,主串指针无需回溯,并根据前后缀匹配数组中的信息,向后移动,从而减少了多余的比较。
代码实现:
// KMP算法
int kmp(SString &s, SString &t, int pos){
int next[t.length], j = 0, i = 0;
get_next(t, next);
while (i < s.length && j < t.length){
if (j == -1 || s.ch[i] == t.ch[j]){
i++; j++;
} else
j = next[j];
}
if (j >= t.length)
return i-t.length;
else
return -1;
}
void get_next(SString &t, int next[]){
int i = 0, j = -1;
next[0] = -1;
while (i < t.length - 1){
if (j == -1 || t.ch[i] == t.ch[j]){
i++; j++;
next[i] = j;
} else {
j = next[j];
}
}
}
参考博客:
可运行的整体代码:
#include<iostream>
#define MAXLEN 100
#define CHUNKSIZE 50
using namespace std;
// 串的普通顺序存储
typedef struct {
char ch[MAXLEN+1];
int length;
}SString;
// 串的堆式顺序存储
//typedef struct {
// char *ch;
// int length;
//}SString;
// 串的链式存储
typedef struct chunk{
char ch[CHUNKSIZE];
struct chunk *next;
}Chunk;
typedef struct {
Chunk *head, *tail;
int length;
}LString;
// 普通顺序存储的初始化操作
void SsInit(SString &s){
s.length = 0;
}
void SsInput(SString &s){
char c;
while ((c = getchar()) != '
'){
s.ch[s.length++] = c;
}
}
void printString(SString &s){
for (int i = 0; i < s.length; i++){
cout << s.ch[i];
}
cout << endl;
}
// BF算法 - O(mn)
int pm(SString s, SString t, int pos){
for (int i = pos; i <= s.length-t.length; i++){
bool status = true;
for (int j = 0; j < t.length; j++){
if (s.ch[i+j] != t.ch[j]){
status = false;
break;
}
}
if (status)
return i;
}
return -1;
}
// 另一种版本的BF算法 O(mn) - 与暴力法相似
int bf(SString s, SString t, int pos){
int i = pos, j = 0;
while (i < s.length && j < t.length){
if (s.ch[i] == t.ch[j]){
i++;
j++;
} else {
i = i - j + 1;
j = 0;
}
}
if (j >= t.length)
return i - t.length;
else
return -1;
}
// KMP算法
int kmp(SString &s, SString &t, int pos){
int next[t.length], j = 0, i = 0;
get_next(t, next);
while (i < s.length && j < t.length){
if (j == -1 || s.ch[i] == t.ch[j]){
i++; j++;
} else
j = next[j];
}
if (j >= t.length)
return i-t.length;
else
return -1;
}
void get_next(SString &t, int next[]){
int i = 0, j = -1;
next[0] = -1;
while (i < t.length - 1){
if (j == -1 || t.ch[i] == t.ch[j]){
i++; j++;
next[i] = j;
} else {
j = next[j];
}
}
}
int main(){
SString s, t;
SsInit(s);
SsInput(s);
SsInit(t);
SsInput(t);
int loc = -1;
// loc = pm(s, t, 0);
// loc = bf(s, t, 0);
loc = kmp(s, t, 0);
cout << loc << endl;
}