字符串匹配算法c语言,【C语言实现】字符串匹配—Sunday算法

简书内代码已上传GitHub:点击我 去GitHub查看代码

如果有疑问,私信交流-……-

如有错误,大佬们一定留言指出呀!!

因为开始刷leetcode题,所以接触到了sunday算法,题目如下:

8197738c016a

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

以下是手写的匹配过程:

8197738c016a

匹配过程

偏移量数组的制作:

// 获得偏移量数组

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写一下

每天进步一点,加油!

8197738c016a

End

END

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值