学了一些 kmp的算法,现在来总结一下。。。
首先KMP是用来做字符串匹配的,然后里面 关键在于 next数组,next是 kmp的灵魂首先像求 普通字符串匹配一样 求,
最关键的就在于 j=next【j】 ;
这不仅是一个跳跃的过程,也是一个回溯的过程,如果不匹配 直到j==0 回到开始
然后 关键在于next数组的求法,next数组其实就是 该位置 和 字符串开始位置有多少个相同 的字符数,因为这些字符数都是可以跳过的
用next 数组 还可以求 字符串的周期, 最后一个next【i】
用 字符串长度 len%(len-next【i】) 如果==0,这个字符串就有周期为 len /(len-next【i】)
用 strlen 函数 如果字符串 量太大 也会 超时
可以用KMP求 前缀 和后缀相同的,就是 next[ l e n ]
#include<stdio.h>
#include<string.h>
#define N 10000
int next[10000];
int KMP(char *main_str,char *find_str,int main_len,int find_len) //定义 两个 字符串 和其长度 为了避免多次用str-len超时,在主函数传值进来
{
int i=0,j=0; //i 作为一个 main 计数 j作为find的计数
while(i<main_len && j <find_len) //这里不能用j<strlen(find_str) 因为 strlen为无符号型int,j为负,和无符号比较就是20+亿,就会出问题
// 当 i越界时说明 比较完 没找到子串 j越界说明找到子串
{if(j==-1 || main_str[i] == find_str[j])
{
i++;j++; //i 和j 同时增加 进行比较
}
else
j=next[j]; // next数组是核心 , 进行跳跃 ,同时也可以进行回退,如果为0 就退回 原始点-1
}
if (j>=find_len) //不能用main判断
return i-j+1;
else
return 0;
}
void get_next(char *find_str,int find_len) //精华
{
int i=0,j=-1; //j作为 回退的标志
next[0]=-1; // 回退的初始点
while(i<find_len)
{
if(j==-1 || find_str[i]==find_str[j])
{
i++;
j++;
next[i]=j; //记录 相比配对成功的 j
}
else
j=next[j]; // 配对不成功回退 直到回退到 -1
}
}
int main()
{
char main_str[1000]="hello world,i'm a apple";
char find_str[100];
int main_len=strlen(main_str);
while(scanf("%s",find_str)!=NULL)
{
int find_len=strlen(find_str);
get_next(find_str,find_len);
printf("%d\n",KMP(main_str,find_str,main_len,find_len));
}
}