模式匹配:
1.暴力匹配(BF):模式串和主串,从头开始匹配,如果遇到不匹配,则从头开始重新匹配,主串返回到原来起始位置向后移动一位。
然后一直查找直到最后找到
最后匹配成功,将匹配成功后的剩余主串返回,并且输出。其匹配成功的下标应该为i-j ;
其适用范围为模式串中的重复字符较少的情况,时间复杂度较高,为O(m*n),m为字串长度,n为主串长度,空间复杂度较低为O(1)。
//暴力匹配 ,时间复杂度O(m*n)m为子串长度,n为主串长度 BF
char *my_strstr1(char *string, const char *strCharSet)
{
assert(string != NULL && strCharSet != NULL);
char *pdest = string;
const char *psrc = strCharSet;
int i, j;
i = j = 0;
while (pdest[i] != '\0'&& psrc[j] != '\0')
{
if (pdest[i]==psrc[j])
{
i++;
j++;
}
else{
i = i - j + 1;
j = 0;
}
}
if (psrc[j] == '\0')
return string + i - j;
else
return NULL;
}
int main()
{
char s[] = "abababababaaaabababc";
char t[] = "abababc";
char *ar=my_strstr(s, t);
printf(" s = %s\n", ar);
system("pause");
return 0;
}
2.快速匹配(KMP):
对于暴力算法,如果出现不匹配字符,同时回退 主串和模式串的指针,嵌套 循环,时间复杂度 O(MN),空间复杂度 O(1)。
KMP相对于暴力匹配来说时间复杂度大大降低,只需要O(m+n),
对于KMP算法来说最主要的还是next 数组的实现。
不说了,老表上图。
下面的规律根据上面前后缀的最长相等长度很容易得到
写出next数组代码为:
void Next(char *pdest, int *next)
{
int len = strlen(pdest);
next[0] = 0;
int j = 0;
for (int i = 1; i < len; ++i)
{
while (j>0 && pdest[j] != pdest[i])
j = next[j - 1];
if (pdest[j] == pdest[i])
j++;
next[i] = j;
}
}
得到了next 数组,老表们就可以根据next数组来进行匹配了,咱们接着上图,
主串与模式串进行匹配,主要不同于BF的方面为,主串指针不回说,当匹配不当时,只移动模式串指针。
当模式串与主串不匹配时,模式串指针根据next数组,进行回溯,
其指针回溯到其前一个next数组的值, 再此进行匹配,直到循环结束,
在这里插入代码片 while (pdest[i] != '\0' && psrc[j] != '\0')
{
if (pdest[i] == psrc[j])
{
i++;
j++;
}
else{
j = next[j-1];
}
}
循环有两个出口,判断其出口到底是匹配成功还是失败,成功就将后面的字符串返回,失败则返回-1.
最后,给大家附上KMP总代码
#include<stdio.h>
#include<windows.h>
#include<assert.h>
#include<string.h>
#include<stdbool.h>
#pragma warning(disable:4996)
void Next(char *pdest, int *next)
{
int len = strlen(pdest);
next[0] = 0;
int j = 0;
for (int i = 1; i < len; ++i)
{
while (j>0 && pdest[j] != pdest[i])
j = next[j - 1];
if (pdest[j] == pdest[i])
j++;
next[i] = j;
}
}
char *my_strstr2(char *string, char *strCharstring)
{
assert(string != NULL && strCharstring != NULL);
char *pdest = string;
char *psrc = strCharstring;
int next[7];
Next(psrc, next);
int i, j;
i = j = 0;
while (pdest[i] != '\0' && psrc[j] != '\0')
{
if (pdest[i] == psrc[j])
{
i++;
j++;
}
else{
j = next[j-1];
}
}
if (psrc[j] == '\0')
return string + i - j;
else
return NULL;
}
int main()
{
char s[] = "abababababaaaabababcccccc";
char t[] = "abababc";
char *ar = my_strstr2(s, t);
printf(" s = %s\n", ar);
system("pause");
return 0;
}
欢迎大家指点。