1、BF算法(暴力算法)(Brute Force):
字符串匹配问题:
主串:“ababcabcdabcdeb”
子串:“abcd”
子串个数:(1+n)*n/2+1
真子串个数:(1+n)*n/2
目的:在主串中找到子串第一次开始出现的位置。
**BF算法难点:**容易出错(i没有回退)
1、两两比较,如果相等,i++,j++,接着向后比
2、如果匹配到一半发现不相等了,就返回到主串中这趟比较的下一个位置,i=i-j+1,
j回退到0
3、如果主串中的i走出了位置,那么并不能判断是否找到了子串相匹配
4、只能利用j是否等于字串长度来判断是否找到
#include<stdio.h>
#include<assert.h>
#include<string.h>
/*
BF算法:唯一注意一点,容易出错(i没有回退)
1、两两比较,如果相等,i++,j++,接着向后比
2、如果匹配到一半发现不相等了,就返回到主串中这趟比较的下一个位置,i=i-j+1,
j回退到0
3、如果主串中的i走出了位置,那么并不能判断是否找到了子串相匹配
4、只能利用j是否等于字串长度来判断是否找到
*/
int BF_Search(const char* s1, const char* s2, int pos)//pos为从主串的pos下标开始找
{
assert(s1 != NULL && s2 != NULL);
if (pos < 0 || pos >= strlen(s1))
{
//return -1
pos = 0;//默认改成从零号下标开始找
}
int len1 = strlen(s1);//保存主串长度
int len2 = strlen(s2);//保存子串长度
int i = pos;//主串开始位置
int j = 0;//字串开始位置
while (i < len1 && j < len2)
{
if (s1[i] == s2[j])
{
i++;
j++;
}
else
{
i = i - j + 1;//如不相等时回退到主串开始匹配的地方的下一个位置
j = 0;
}
}
if (j == len2)
{
return i - j;
}
else
{
return -1;
}
}
int main()
{
const char* s1 = { "adadadadacdda" };
const char* s2 = { "dacd" };
int a=BF_Search(s1, s2, 3);
printf("%d\n", a);
}
优点:思想简单,好实现
**缺点:**效率低下,时间复杂度O(n*m)
2、KMP算法
kmp就是三个外国人名字,kmp主要思想就是不回退
找next数组:
"abcdabcde": -1 0 0 0 0 1 2 3 4
"ababcababca":-1 0 0 1 2 0 1 2 3 4 5
**“ababcababcaba”:-1 0 0 1 2 0 1 2 3 4 5 6 **可以重复
获得子串next数组元素函数
#include<stdio.h>
#include<stdlib.h>
#include<assert.h>
#include<string.h>
//s2为子串
int* Get_next(const char* s2)//"ababcababcab"--->-1 0 0 1 2 0 1 2 3 4 5 6前两个必是-1和0
{
assert(s2 != NULL);
int len2 = strlen(s2);
int* next = (int*)malloc(sizeof(int) * len2);
assert(next != NULL);
int j = 0;
int k = -1;
next[0] = -1;
next[1] = 0;
while (j < strlen(s2))
{
if (s2[j] == s2[k] || k == -1)//比较如果
{
j++;
k++;
next[j] = k;
}
else
{
k = next[k];
}
}
return next;
}
KMP算法:
int KMP(const char* s1, const char* s2, int pos)
{
assert(s1 != NULL && s2 != NULL);
int len1 = strlen(s1);
int len2 = strlen(s2);
int i = pos, j = 0;
int* next = Get_next(s2);
if (pos<0 || pos>len2)
{
pos = 0;
}
while (i < len1&&j < len2)
{
if (j==-1 ||s1[i] == s2[j])
{
i++;
j++;
}
else
{
j = next[j];
}
}
if (j >= len2)
{
return i - j;
}
else
{
return -1;
}
}
int main()
{
const char* s1 = { "adadadadacdda" };
const char* s2 = { "cdda" };
int a = KMP(s1, s2, 3);
printf("%d\n", a);
}
else
{
return -1;
}
}
int main()
{
const char* s1 = { "adadadadacdda" };
const char* s2 = { "cdda" };
int a = KMP(s1, s2, 3);
printf("%d\n", a);
}