1. 串的简单模式匹配算法
简单模式匹配 Brute-Force(布鲁斯-福斯)算法是一种带回溯的匹配算法,算法的基本思想是:从主串 s 的第一个字符开始,和模式串 t 的第一个字符开始比较,如果相等,就继续比较后续字符,如果不等,则回溯到主串 s 的第2个字符开始重新和模式串 t 比较,直到模式串 t 中的每一个字符和主串 s 中的一个连续字符子序列全部相等,则称匹配成功,返回和 t 中第一个字符相等的字符在主串 s 中的位置;或者主串中没有和模式串相等的字符序列,则匹配不成功。
实现时设三个指示器:i,j,start;i 指向主串 s 中当前比较的字符,j 指向子串 t 中当前比较的字符,start 记录每趟比较时在主串 s 中的起点。
1.1 简单模式匹配算法
/*简单模式匹配算法(有回溯)*/
int StrIndex(SString* s, SString* t) {
int i, j, start = 0;
if (t->len == 0) //模式串为空时是任意串的匹配串
return 0;
i = start, j = 0;
while (i < s->len && j < t->len) {
if (s->ch[i] == t->ch[j]) {
//当前对应字符相等时向前推进
i++;
j++;
}
else {
start++; //当前对应字符不相等时回溯
i = start; //主串从start+1开始
j = 0; //模式串从0开始
}
}
if (j >= t->len)
return start; //匹配成功时,返回匹配起始位置
else
return -1; //匹配不成功,返回-1
}
1.2 完整实现代码
# include<stdio.h>
# define MAXLEN 40
/*顺序串的存储结构*/
typedef struct {
char ch[MAXLEN];
int len;
}SString;
/*顺序串初始化*/
void StrInit(SString* s) {
s->len = 0;
}
/*顺序串赋值*/
void StrAssign(SString* s, char* tval) {
//将字符串常量tval的值赋值给串s
int len, i = 0;
while (tval[i] != '\0')
i++;
len = i;
for (i = 0; i < len; i++)
s->ch[i] = tval[i];
s->len = len;
}
/*简单模式匹配算法(有回溯)*/
int StrIndex(SString* s, SString* t) {
int i, j, start = 0;
if (t->len == 0) {
//模式串为空时是任意串的匹配串
printf("模式串为空!\n");
return 0;
}
i = start, j = 0;
while (i < s->len && j < t->len) {
if (s->ch[i] == t->ch[j]) {
//当前对应字符相等时向前推进
i++;
j++;
}
else {
start++; //当前对应字符不相等时回溯
i = start; //主串从start+1开始
j = 0; //模式串从0开始
}
}
if (j >= t->len) //匹配成功
printf("匹配成功!起始位置为:%d\n", start + 1);
else
printf("匹配失败!\n"); //匹配不成功
}
int main() {
char tval_s[14] = {
'a','b','a','b','c','a','b','c','a','c','b','a','b' };
char tval_t[6] = {
'a','b','c','a','c' };
SString s, t;
StrAssign(&s, tval_s);
StrAssign(&t, tval_t);
StrIndex(&s, &t);
return 0;
}
1.3 运行结果
2. KMP算法
KMP算法详解见 @哈顿之光 的博客:https://blog.csdn.net/weixin_46007276/article/details/104372119?spm=1001.2014.3001.5502
2.1 完整实现代码
# include<stdio.h>
# define MAXLEN 40
/*顺序串的存储结构*/
typedef struct {
char ch[MAXLEN];
int len;
}SString;
/*顺序串初始化*/
void StrInit(SString* s) {
s->len = 0;
}
/*顺序串赋值*/
void StrAssign(SString* s, char* tval) {
//将字符串常量tval的值赋值给串s
int len, i = 0;
while (tval[i] != '\0')
i++;
len = i;
for (i = 0; i < len; i++)
s->ch[i] = tval[i];
s->len = len;
}
int next[MAXLEN];
/*求next[]数组*/
/*next[j]表示模式串t的第j-1个字符前的字符串的最大前后缀*/
void GetNext(SString* t, int* next) {
int j, k;
j = 0; k = -1;
next[0] = -1; //第一个字符前无字符串,赋值-1
while (j < t->len - 1){
if (k == -1 || t->ch[j] == t->ch[k]){
j++;
k++;
next[j] = k;
}
else
k = next[k];
}
}
/*KMP算法*/
int KMPIndex(SString* s, SString* t){
int i = 0, j = 0;
while (i < s->len && j < t->len){
if (j == -1 || s->ch[i] == t->ch[j]){
i++;
j++;
}
else
j = next[j];
}
if (j >= t->len)
return(i - t->len + 1); //返回匹配模式串的首字符下标+1
else
return(-1); //返回不匹配标志
}
int main() {
char tval_s[14] = {
'a','b','a','b','c','a','b','c','a','c','b','a','b' };
char tval_t[6] = {
'a','b','c','a','c' };
SString s, t;
StrAssign(&s, tval_s);
StrAssign(&t, tval_t);
GetNext(&t, next);
printf("%d\n", KMPIndex(&s, &t));
return 0;
}
2.2 运行结果
更多数据结构内容关注我的《数据结构》专栏:https://blog.csdn.net/weixin_51450101/category_11514538.html?spm=1001.2014.3001.5482