串的模式匹配(c实现)
KMP模式匹配的核心思想:
省略一部分不必要的判断步骤(即去掉没必要的回溯步骤)
主串和匹配串分别的改变方式:
主串:是不会跳跃性改变,而只是会依次的递增比较下去
匹配串:根据匹配失败的串的后缀串与前缀串的匹配程度,从而确定回溯的位置
算法的实现:
分两块(两个函数):
First:一个能计算出匹配串中每一个位置匹配失败后,需回溯的位置的函数。
Second:一个能将匹配串和主串相比较匹配的函数。
KMP算法的重点考研考点: next数组
1.理解KMP使用前后缀来进行子串匹配:即在子串和主串比较时,j值得多少取决于当前字符之前的串的前后缀的相似程度。
2.next数组理解:用来高效地判断子串中是否含有相同的前后缀及匹配失败时如何利用这些信息。
更多例题:
代码实现:
///KMP模式匹配算法实现
///计算出匹配串中每一个位置匹配失败后,需回溯的位置
///即生成next数组
void get_next(String T,int *next){
int i,j;
int i = 1;
int j = 0;
next[1] = 0;
while(i<T[0]) // 此处的T[0]表示串T的长度
{
if(j==0||T[i]==T[j]){
//T[i]表示后缀的单个字符
//T[j]表示前缀的单个字符
++i;
++j;
next[i] = j;
}
else j = next[j]; //若字符不相同,则j回溯
}
}
#define MAX 255
///KMP模式匹配算法实现
///计算出匹配串中每一个位置匹配失败后,需回溯的位置
///即生成next数组
void get_next(String T,int *next){
int i,j;
int i = 1;
int j = 0;
next[1] = 0;
while(i<T[0]) // 此处的T[0]表示串T的长度
{
if(j==0||T[i]==T[j]){
//T[i]表示后缀的单个字符
//T[j]表示前缀的单个字符
++i;
++j;
next[i] = j;
}
else j = next[j]; //若字符不相同,则j回溯
}
}
///返回子串T在主串S中第pos个字符之后的位置。若不存在则返回0
int Index_KMP(String s,String T,int pos){
int i = pos; //i用于表示主串S当前位置下的标值
int j = 1;
int next[MAX]; //定义一next数组
get_next(T,next); //得到next数组
while(i<=s[0]&&j<=T[0]){
if(j==0||s[i]==T[j]){
++i;
++j;
}
else{
j = next[j];
}
}
if(j>T[0]) return i-T[0];
else return 0;
}
#include<stdio.h>
#include <string.h>
#define MaxSize 100
/*
实现KMP算法:
1.get_next(String T,int *next)//传入一个匹配串得到他的next数组
2.Index_KMP(String S,String T)//返回模式串在匹配串中的位置
*/
//define a String,store from 1
typedef struct {
char ch[MaxSize];
int len;
}String;
//next[i]记录的为此前串中的最长公共前后缀的长度
//回溯的含义:当前第i个位置不匹配,但我们之前的i-1个位置都是匹配的,我们可以找到它的最长公共前后缀进行移动再比较
void get_next(String T, int* next) {
int i, j;//只有j进行回溯
i = 1;
j = 0;
next[1] = 0;
while (i < T.len) {
if (next[i] == next[j]) {
i++;
j++;
next[i] = j;
}
else
{
j = next[i];//匹配失败进行回溯
}
}
}
int Index_KMP(String S, String T) {
int i = 1, j = 1;
int next[100];
get_next(S, next);
while (i <= S.len && j <= T.len) {
if (j == 0 || S.ch[i] == T.ch[j]) {
i++;
j++;
}
else {
j = next[j];
}
}
if (j > T.len) {
return i - T.len;
}
else
{
return 0;
}
}
int main() {
//printf("Start");
String T;
String S;
T.len = 5;
//printf("Start1");
strcpy(T.ch,"0abbaa");
S.len = 11;
strcpy(S.ch, "0abbabbabbaa");
//printf("Start2");
printf(S.ch);
printf("\n");
printf(T.ch);
printf("\n");
//int next[5];
//get_next(T, next);
//for(int i=0;i<5;i++)
// printf("%d",next[i]);
//printf("\n");
int locat = Index_KMP(S, T);
printf("Start3");
printf("locat:%d", locat);
return 0;
}
疫情期间,希望自己能放下心中的躁动,用学习丰富自己。