目录
4.2_1 朴素模式匹配算法
一、什么是字符串的模式匹配
在一段文字中搜索某一段内容。
主串:被搜索的字符串。
模式串:想要搜索的内容。
字符串模式匹配:在主串中找到与模式串相同的子串,并返回其所在位置。
* 子串——主串的一部分,一定存在;
模式串——不一定能在主串中找到;
二、朴素模式匹配算法
因为模式串T的长度为6,所以就把主串S中长度为6的字符串与模式串T一一对比。
主串长度为n,模式串长度为m。
朴素匹配模式算法:将主串中所有长度为m的子串依次与模式串对比(最多对比n-m+1个子串),直到找到一个完全匹配的子串,或所有的子串都不匹配为止。
(1)使用字符串基本操作来实现
上一节代码实现中Index(S, T)函数就是用的这种算法。
// (8)求子串。用Sub返回串S的第pos个字符起长度为len的字符串
bool SubString(SString &Sub, SString S, int pos, int len){
// 子串范围越界
if(pos+len-1 > S.length){
return false;
}
// 把S的子串一个个填进Sub字符串里,并给Sub长度赋值
for(int i = pos; i < pos+len; i++){
Sub.ch[i-pos+1] = S.ch[i];
}
Sub.length = len;
return true;
}
// (9)比较操作。若S>T,则返回值>0;若S=T,则返回值=0;若S<T,则返回值<0。
int StrCompare(SString S, SString T){
for(int i = 1; i <= S.length && i <=T.length; i++){
if(S.ch[i] != T.ch[i]){
return S.ch[i] - T.ch[i];
}
}
// 扫描过的所有字符都相同,则长度长的串更大
return S.length - T.length;
}
// (10)定位操作。 若主串S中存在与串T值相同的子串,则返回它在主串S中第一次出现的位置;否则函数值为0.
int Index(SString S, SString T){
int i = 1, n = StrLength(S), m = StrLength(T);
SString sub; // 用于暂存子串
while(i <= n-m+1){
SubString(sub, S, i, m); // 求子串
if(StrCompare(sub, T) != 0){
++i;
}
else{
return i; // 返回子串在主串中的位置
}
}
return 0; // S中不存在与T相等的子串
}
(2)通过数组下标来实现
不使用字符串的基本操作,直接通过数组下标实现朴素模式匹配算法。
(1)S[i]与T[j]字符进行比较,看是否匹配
(2)若当前子串匹配失败,则主串指针i指向下一个子串的第一个位置,模式串指针j回到模式串的第一个位置。
i = i - j + 2;
j = 1;
(3)若j > T.length,则当前子串匹配成功,返回当前子串第一个字符的位置(i - T.length)
运行结果:
实现代码:
// 20220605 朴素模式匹配算法
#include<iostream>
#include<cstring>
using namespace std;
// 串的静态数组存储
#define MAXLEN 255
typedef struct{
char ch[MAXLEN]; // 串中字符存储(从下标1开始存)
int length; // 串长度
}SString;
// 朴素模式匹配
int Index(SString S, SString T){
int i = 1, j = 1;
while(i <= S.length && j <= T.length){
cout << "S.ch[i]:" << S.ch[i] << ",T.ch[j]:" << T.ch[j] << endl;
if(S.ch[i] == T.ch[j]){ // 如果