BF和KMP算法

BF算法

                       

KMP算法:

 

 

 

 

算法相关代码:

/*
   BFANDKMP.h 文件
*********************
*/
#ifndef __BFANDKMP_H
#define __BFANDKMP_H

#include <stdio.h>
#include <string.h>
#include <assert.h>
#include <malloc.h>

//利用BF思想解决串匹配
int BF(const char *s, const char *p, int pos);//从s串的pos位置开始寻找匹配p串的位置

//利用KMP思想解决串匹配
int KMP(const char *s, const char *p, int pos);//从s串的pos位置开始寻找匹配p串的位置

//寻找字符数组p的next数组
void GetNext(const char *p, int *next);

#endif


/*
   BFANDKMP.c 文件
*********************
*/
#include "BFANDKMP.h"

//利用BF思想解决串匹配,从s串的pos位置开始寻找匹配p串的位置
int BF(const char *s, const char *p, int pos)
{
	assert(s != NULL && p != NULL);

	int lens = strlen(s);//分别求出两个字符串的有效长度
	int lenp = strlen(p);

	if(lenp > lens )//先检查原字符长度是否大于等于目的字符串
	{
		return -1;
	}
	int i = pos; //从pos位置开始寻找匹配目的字符串的位置,因为可能目的字符串不止一次出现在原字符串中
	int j = 0;
	while( i < lens && j < lenp)
	{
		if( s[i] == p[j])//如果两个元素相等,则比较各自的下一个字符
		{
			i++;
			j++;
		}
		else
		{
			i = i - j + 1;
			j = 0;
		}
	}
	if( j == lenp)
	{
		return i - j; //如果j越界,则代表p串中的所有字符已经匹配完毕,输出匹配位置
	}
	return -1;//如果i越界则代表匹配不成功
}

//利用KMP思想解决串匹配,从s串的pos位置开始寻找匹配p串的位置
void GetNext(const char *p, int *next) 
{
	//   因为在调用这个函数的KMP函数中,在调用之前已经断言过p和next不能为空,
	//所以在这里可以不用再判断两个指针是否为空
	int i = 1;
	int k = 0;  //next数组前两个值是默认的值
	int len = strlen(p);

	next[0] = -1;
	next[1] = 0;

	//利用KMP思想求匹配的真子串的长度存到next中
	while( i + 1 < len )
	{
		if(p[k] == p[i] || k == -1)
		{
			next[i+1] = k + 1;
			i++;
			k++;
		}
		else
		{
			k = next[k];
		}
	}
}

int KMP(const char *s, const char *p, int pos)
{
	assert(s != NULL && p != NULL);

	int lens = strlen(s);
	int lenp = strlen(p);
	if( lenp > lens)
	{
		return -1;
	}
    int i = pos ;   //   i代表以源字符串中pos号下标开始到字符串结束中寻找匹配的目的串的匹配位置。
    int j = 0;      //pos的值时用户来决定的
	    
	int *next = (int *)malloc(sizeof(int) * strlen(p)); //为目的串的next数组申请空间
	assert( next != NULL);

	GetNext(p, next);
	while( i < lens && j < lenp)//在i和j都不越界的条件下重复循环寻找匹配位置
	{
		if( j == -1 || s[i] == p[j])//   在else语句中,j有可能因为在回退途中没有相等的真子串而回退到
		{                           //next[0]代表的位置,所以j有可能会被赋值为“-1”,因此这里if语句
			i++;                    //的判断条件得加上“j == -1”如果等于进入语句后j被重新赋值为0,
			j++;                    //然后重新开始从目的串的头与源字符串比较寻找匹配位置(所以会在初始
		}                           //时将next[0]赋值为-1是为了利用现有的语句让j直接回到目的串的头位置)
		else
		{
			j = next[j];
		}
	}
	free(next);          //free必须在return之前

	if( j == lenp)    //   如果目的串先越界,证明j下标之前的字符已经和源字符串相匹配,
	{                 //所以返回在源字符串中开始匹配的位置
		return i - j;
	}
	return -1;        //   如果跳出循环的条件不是j越界,则代表时i越界了,i越界就证明在遍历完源字符串
	                  //后还是没有找到匹配的目的字符串,所以返回错误值-1
}

/*
   main.c 测试文件
*********************
*/
#include "BFANDKMP.h"

int main()
{
    //测试KMP思想实现
	char s[] = "abcdesfsdfsdf";
	char p[] = "sfsd";
	
	printf("%d\n",KMP(s, p, 1));
	printf("%d\n",KMP(s, p, 6));
	printf("%d\n",KMP(s, p, 8));

   //测试BF思想实现
	//char s[] = "abcdesfsdfsdf";
	//char p[] = "sfsd";
	//printf("%d\n",BF(s, p, 2));
	//printf("%d\n",BF(s, p, 10));
	
	return 0;
}

猜你喜欢

转载自blog.csdn.net/xing1584114471/article/details/83063761