串的主要算法实现

(bf)朴素算法与kmp算法的实现:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define MAXSIZE 100

typedef struct
{
	char data[MAXSIZE];
	unsigned int length;//字符串中元素的个数
}string;

//动态分配内存
typedef struct {
	char* data;//动态分配数组长度
	unsigned int maxsize;//字符串最大长度
	unsigned int length;//字符串实际长度
}String;

typedef struct LNode
{
	char data;//每个结点一个字符
	struct LNode* next;//存储密度低
}LNode,*StringLink;

typedef struct Lnode {
	char data[MAXSIZE];//每个结点存储maxsize个字符
	struct Lnode* next;
}Lnode,*stringlink;


//bf算法的实现
// 采用BF算法,查找在目标串sstr中模式串tstr出现的位置,字符串的起始位置从0开始。
// 只要在目标串sstr中找到了第一个模式串tstr,函数就返回。
// 成功返回模式串tstr在目标串sstr中第一次出现的数组下标,失败返回-1。
int index_bf(char sstr[], char tstr[])
// int index_bf(char *sstr,char *tstr)
{
	if ((sstr == 0) || (tstr == 0)) return -1;//空串结尾的‘/0’作为判断条件哦
	//目标串sstr和模式串从数组下标0开始找
	//依题意有可能是空出0
	int ii = 0, jj = 0;//循环都从0开始
	int slen = strlen(sstr), tlen = strlen(tstr);

	while ((ii < slen) && (jj < tlen)) {
		if (sstr[ii] == tstr[jj]) {
			ii++;
			jj++;
		}
		else {
			//否则不匹配回到前面数组下标的后一个小标
			ii = ii - jj + 1;
			jj = 0;//目标船和模式串的指针都要回溯
		}
	}
	if (jj == tlen)
		//说明匹配成功
		return ii - jj;//返回当前下标要看好题意可能要加一
	//没返回
	return -1;
}

// 根据模式串tstr,计算next数组,字符串的起始位置从0开始。
// void getnext(char *tstr,int *next)
void getnext(char tstr[], char next[]) {
	if ((tstr == 0) || (next == 0)) return;  // 判断空指针。

	int tlen = strlen(tstr);  // 模式串的长度。

	// 如果模式串的长度小于3,无需计算next数组,直接返回。
	if (tlen == 0) return;
	if (tlen == 1) { next[0] = -1; return; }
	if (tlen == 2) { next[0] = -1; next[1] = 0; return; }

	next[0] = -1;  // 位置0直接填入-1。
	next[1] = 0;   // 位置1直接填入0。

	int ii;
	// 循环从2开始,位置0和1不必计算。
	for (ii = 2; ii < tlen; ii++)
	{
		int maxlen = 0;  // 最长公共前后缀的长度。

		// 用一个循环,得到全部的前缀和后缀,并判断最长公共前后缀。
		int jj = 1;
		for (jj = 1; jj < ii; jj++)
		{
			char p1[tlen], p2[tlen];
			memset(p1, 0, sizeof(p1));
			memset(p2, 0, sizeof(p2));

			//去前后缀
			//记住next数组回溯位置就是失败前的那个位置之前的最长前后缀匹配的最长长度+1
			strncpy(p1, tstr, jj);//取一个前缀随着循环次数取得前缀++
			strncpy(p2, tstr, tstr + ii - jj, jj);//去后缀
			//判断是否相同
			if (strcmp(p1, p2) == 0) maxlen = jj;
		}
		next[ii] = maxlen;
	}
	return;
}

// 根据模式串tstr和next数组计算nextval数组,字符串的起始位置从0开始。
// void getnextval(char *tstr,int *next,int *nextval)
//建立在next数组的基础上看看next数组下标指向的位置是否其next数组重合
void getnextval(char tstr[], int next[], int nextval[])
{
	if ((tstr == 0) || (next == 0) || (nextval == 0)) return;  // 判断空指针。
	int tlen = strlen(tstr);
	nextval[0] = -1;
	int ii;
	//nextval第0个位置不用管直接看1往后的位置
	for (ii = 1; ii < tlen; ii++) {
		if (tstr[ii] == tstr[next[ii]]) {
			nextval[ii] = nextval[next[ii]];
		}
		else {
			nextval[ii] = next[ii];
		}
	}
}

// 采用kmp算法,查找在目标串sstr中模式串tstr出现的位置,字符串的起始位置从0开始。
// 只要在目标串sstr中找到了第一个模式串tstr,函数就返回。
// 成功返回模式串tstr在目标串sstr中第一次出现的数组下标,失败返回-1。
// int index_kmp(char *sstr,char *tstr)
int index_kmp(char sstr[], char tstr[],int tlen ){
	if ((sstr == 0) || (tstr == 0)) return -1;  // 判断空指针。
	// 目标串sstr和模式串tstr都从数组下标0开始。
	int ii = 0, jj = 0;
	int slen = strlen(sstr), tlen = strlen(tstr);//这里好像下面建立数组之前要常量所以真要考的话在main函数里面先算出来然后
	//index_kmp(char sstr[], char tstr[],int slen,int tlen)即可
	// 获取next数组。
	int next[tlen];
	getnext(tstr, next);
	// 根据模式串tstr和next数组计算nextval数组,字符串的起始位置从0开始。
	int nextval[tlen];
	getnextval(tstr, next, nextval);
	//有了nextval数组之后就乱杀
	while ((ii < slen) && (jj < tlen)) {
		if ((jj = -1) || (sstr[ii] = tstr[jj])) {
			ii++;
			jj++;
		}
		else {
			//不相等找nextval数组中的值
			jj = nextval[jj];
		}
	}
	//判断是否匹配成功哈成功返回头个元素
	if (jj == tlen) return ii - tlen;
	return -1;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值