简书内代码已上传GitHub:点击我 去GitHub查看代码
如果有疑问,私信交流-……-
如有错误,大佬们一定留言指出呀!!
因为开始刷leetcode题,所以接触到了sunday算法,题目如下:
Leetcode28
一.暴力求解
时间复杂度:O(n * m):
直接两层循环套上,一个一个匹配,匹配失败右移一位,继续重新匹配。代码很简单:
int strStr(char * haystack, char * needle){
//获得长度
int haystacklen = strlen(haystack);
int needlelen = strlen(needle);
//标记比较的状态
int flag = 0;
//数组为空返回0
if(!haystacklen && !needlelen){
return 0;
}
//O(n*m)暴力求解
for(int i = 0 ; i < haystacklen ; ++i){
flag = 0;
for(int j = 0 ; j < needlelen ; ++j){
//不匹配改变标记值
if(haystack[ i + j ] != needle[ j ]){
flag = 1;
break;
}
}
//成功找到第一个匹配的,返回i
if(!flag){
return i;
}
}
return -1;
}
二.Sunday算法
时间复杂度O(n / m) ~ O(n * m) , 在一般情况下,它是极其高效的。
Sunday算法是Daniel M.Sunday于1990年提出的字符串模式匹配算法。
在匹配失败时关注文本主串中参加匹配的最末位字符的下一位字符
如果该字符没有在匹配串中出现则直接跳过,即偏移量 = 匹配串长度 + 1
否则,其偏移量 = 匹配串中最右端的该字符到末尾的距离 + 1
以下是手写的匹配过程:
匹配过程
偏移量数组的制作:
// 获得偏移量数组
void get_next(int * next, int len){
for(int i = 0 ; i < len ; ++i){
next[i] = len - i;
}
}
判断字符是否在字符串中
// 逆序判断元素字符是否在字符串中,在的话返回第一个下标,否则返回-1
int In(char c, char * needle){
for(int i = strlen(needle) - 1 ; i >= 0 ; --i){
if(c == needle[i])
return i;
}
return -1;
}
算法部分
int i = 0, j = 0;
while(i < len1 && j < len2){
// 依次判断,相等 i 、 j自增
if(haystack[i] == needle[j]){
++i;
++j;
}else{
// 如果索引下标超出范围,结束搜索
if(i + len2 - j > len1)
break;
// 获得元素在needle串中的索引(逆序第一个)
int index = In(haystack[i + len2 - j], needle);
// 元素在串内,按偏移量数组进行偏移
if(index != -1){
i += (next[index] - j);
j = 0;
}else
// 不在串内,直接整体移到该元素后
i += len2 + 1 - j;
}
}
三.完整代码:
// sunday算法求解
#include
#include
#include
// 获得偏移量数组
void get_next(int * next, int len){
for(int i = 0 ; i < len ; ++i){
next[i] = len - i;
}
}
// 逆序判断元素字符是否在字符串中,在的话返回第一个下标,否则返回-1
int In(char c, char * needle){
for(int i = strlen(needle) - 1 ; i >= 0 ; --i){
if(c == needle[i])
return i;
}
return -1;
}
int strStr(char * haystack, char * needle){
// 获得字符串长度
int len1 = strlen(haystack);
int len2 = strlen(needle);
// 如果是空串,返回0
if(len1 == 0 && len2 == 0)
return 0;
// 获得偏移量数组
int * next = (int*)malloc(sizeof(int) * len2);
get_next(next, len2);
int i = 0, j = 0;
while(i < len1 && j < len2){
// 依次判断,相等 i 、 j自增
if(haystack[i] == needle[j]){
++i;
++j;
}else{
// 如果索引下标超出范围,结束搜索
if(i + len2 - j > len1)
break;
// 获得元素在needle串中的索引(逆序第一个)
int index = In(haystack[i + len2 - j], needle);
// 元素在串内,按偏移量数组进行偏移
if(index != -1){
i += (next[index] - j);
j = 0;
}else
// 不在串内,直接整体移到该元素后
i += len2 + 1 - j;
}
}
// 成功匹配
if(j == len2)
return i - len2;
return -1;
}
// 测试
int main(){
char a[] = "mississippi", b[] = "sipp";
printf("%d",strStr(a, b));
return 0;
}
KMP整晕了才写的Sunday,改天用KMP写一下
每天进步一点,加油!
End
END