1. 字符串中的真子串和子串概念
字符串:“abcd” 真子串:“a”,“b”,“c”,“d”,“ab”,“bc”,“cd”,“abc”,“bcd” 子串:" ",“a”,“b”,“c”,“d”,“ab”,“bc”,“cd”,“abc”,“bcd”,“abcd” 真子串:n*(n+1)/2 ; 子串:n*(n+1)/2 +1
2. BF算法
BF算法(暴力求解)也叫男朋友算法 主串:“ababcabcdabcde” 子串:“abcd” 要在主串里面找子串,如果当前光标在主串的0号位置所指,那么就是返回5;如果光标在主串的7号位置指向,那么就返回9。 第一种BF算法: 如果i和j指向的字符相同,则i++,j++;如果i和j指向的字符不相同,则j=0,重新开始比较;退出条件:当i或者j向后走,越界了。 因此,看子串在找到还是没找到是只用看j即可,j如果走出自身范围,则找到了,否则没找到。 第二种BF算法: 如果i和j指向的字符相同,则i++,j++;如果i和j指向的字符不相同,则i=i-j+1,j=0;退出条件:如果i或者j走出自身范围(越界),退出之后,我们需要判断到底子串是否在主串中出现与否,只需要判断j即可;j如果走出自身范围,则找到了,return i-j;j如果没有走出自身范围,则没有找到,return -1; BF算法最经典图: 代码实现:
#include<stdio.h>
#include<assert.h>
#include<stdlib.h>
#include<string.h>
int BF_Search(const char* str, const char* sub, int pos)
{
assert(str != NULL && sub != NULL && pos >= 0 && pos < strlen(str));
int i = pos;
int j = 0;
int len_str = strlen(str);
int len_sub = strlen(sub);
while (i < len_str && j < len_sub)
{
if (str[i] == sub[j])
{
i++;
j++;
}
else
{
i = i - j + 1;
j = 0;
}
}
if (j < len_sub)
{
return -1;
}
else
{
return i - j;
}
}
int main()
{
const char* str = "ababcabcdabcde";
const char* sub = "abcd";
int tmp = BF_Search(str, sub, 0);
if (tmp >= 0)
{
printf("找到了,开始下标为%d\n", tmp);
}
else
{
printf("没有找到");
}
return 0;
}
BF算法的优缺点: 优点:逻辑简单,实现也简单 缺点:效率很低
3.KMP算法
KMP算法就是对BF算法的一个优化 算法:i打死不回退;模式匹配串只与子串有关系
#include<stdio.h>
#include<assert.h>
#include<stdlib.h>
#include<string.h>
int *Get_Next(const char* sub)
{
assert(sub != NULL);
int len = strlen(sub);
int* next = (int*)malloc(len * sizeof(int));
assert(next != NULL);
next[0] = -1;
next[1] = 0;
int j = 1;
int k = next[1];
while (j + 1 < len)
{
if (k == -1||sub[j] == sub[k])
{
k++;
j++;
next[j] = k;
}
else
{
k = next[k];
}
}
return next;
}
int KMP_Search(const char* str, const char* sub, int pos)
{
assert(str != NULL && sub != NULL && pos>=0 && pos<strlen(str));
int i = pos;
int j = 0;
int len_str = strlen(str);
int len_sub = strlen(sub);
int *next = Get_Next(sub);
while (i < len_str && j < len_sub)
{
if (j==-1 || str[i] == sub[j])
{
i++;
j++;
}
else
{
j = next[j];
}
}
if (j < len_sub)
{
return -1;
}
else
{
return i - j;
}
}
int main()
{
const char* str = "ababcabcdabcde";
const char* sub = "abcd";
int flag = KMP_Search(str, sub, 0);
if (flag >= 0)
{
printf("找到了,开始下标为%d\n", flag);
}
else
{
printf("没有找到");
}
return 0;
}
运行结果:
4.BF算法和KMP算法时间复杂度
BF算法:由于会将主串遍历多次,假设最差情况下,整体时间复杂度O(n*m) KMP算法:由于i打死不回退,只会遍历一遍,整体时间复杂度为O(n+m) 因此,KMP算法是BF算法的优化算法。
|