来烤馍片咯(误


KMP算法学习总结

一、为啥要烤馍片

幼稚(朴素)字符串匹配法的时间复杂度为O(n²),并且指示主串的指针要来回回溯,看起来非常的不聪明。此时采用KMP算法,应用next数组,使得指示主串的指针不进行回溯且将时间复杂度降为O(m+n) (写的有点粗略

二、求函数

1.求next数组

a)手动求的方法(适合模式串较短且在选择题中应用)

贴出来手写笔记

b)写成伪代码

思路:虚拟一个重复的模式串并定义next[j]=t;
情况① Pj == Pt 可以得知next[j+1] == t+1 == next[j+1]+1;
情况② Pj != Pt 可以把原模式串看成主串,重复的模式串看成模式串,即令 t=next[t]
若t==0 next(j+1) == 1

伪代码如下:

int getNext(char substr[],int next[])
{
	int t=0;
	int j=1;
	next[1]=0;
	while(j<strlen(substr))
	{
		if(t==0||substr[t]==substr[j])
		{
			++t;
			++j;
			next[j]=t;
		}
		else{
			t=next[t];
		}
	}

}

c)nextval数组(欠佳

对于AAAAB这种模式串,如果在4号位置(下标从1)A不匹配,则3号,2号位置均不匹配,最终 j=0 考虑将j一步到位直接赋值为0
情况① j=1 nextval[j]=0
情况② j>1
若Pj != Pnext[j] nextval[j]=next[j]
若Pj = Pnext[j] nextval[j] = nextval[ next[j] ]

对next数组的伪代码进行修改可得:

int getNextval(char substr[],int nextval[],int next[])
{
	int t=0;
	int j=1;
	next[1]=0;
	nextval[1]=0;
	while(j<strlen(substr))
	{
		if(t==0||substr[t]==substr[j])
		{
		    next[j+1] = t+1;
		    if(substr(j+1) != substr[next[j+1]])
		    	nextval[j+1] = next[j+1];
		    else
		    	nextval[j+1] = nextval[next[j+1]];
			++t;
			++j;
			
		}
		else{
			t=nextval[t];
		}
	}

}

2.烤馍片

很好理解,指针i,j分别指向主串和模式串下标为1的位置,j匹配到不匹配的地方就j = next[j] 进行回溯 看很多教材下标为0的位置都空出用来存串的长度或者啥的,但个人感觉输入上就有点问题了orz

直接上伪代码:

int KMP(char str[],char substr[])
{
	int i = 1;
	int j = 1;
	int next[101];
	getNext(substr,next);
	while(i<=str.lenth && j<=substr.lenth)
	{
		if(j==0 || str[i]==substr[j])
		{
			i++;
			j++;
		}
		else{
			j=next[j];
		}
	}
	if(j>strlen(substr))
	return i-strlen(substr);
	else return 0;
}

三、烤好了

C语言输入上有些问题,为了使下标从1开始存储,假设主串和模式串都是定长字符串…

源代码:

#include<stdio.h>
#include<string.h>
int getNext(char substr[],int next[])
{
	int t=0;
	int j=1;
	next[1]=0;
	while(j<strlen(substr))
	{
		if(t==0||substr[t]==substr[j])
		{
			++t;
			++j;
			next[j]=t;
		}
		else{
			t=next[t];
		}
	}

}

int KMP(char str[],char substr[])
{
	int i = 1;
	int j = 1;
	int next[101];
	getNext(substr,next);
	while(i<=6 && j<=2)
	{
		if(j==0 || str[i]==substr[j]){
			i++;
			j++;
		}
		else {
			j=next[j];
		}
	}

	if(j>2)
	return i-2;
	else return 0;
	
}

int main()
{
	char str[101];
	char substr[101];
	int next[101];
	int i;
	for(i=1;i<=6;i++){
		scanf("%s",&str[i]);
	}
	for(i=1;i<=2;i++){
		scanf("%s",&substr[i]);
	}
	printf("%d",KMP(str,substr));

}

总结

nextval数组
输入问题

Stkcd [股票代码] ShortName [股票简称] Accper [统计截止日期] Typrep [报表类型编码] Indcd [行业代码] Indnme [行业名称] Source [公告来源] F060101B [净利润现金净含量] F060101C [净利润现金净含量TTM] F060201B [营业收入现金含量] F060201C [营业收入现金含量TTM] F060301B [营业收入现金净含量] F060301C [营业收入现金净含量TTM] F060401B [营业利润现金净含量] F060401C [营业利润现金净含量TTM] F060901B [筹资活动债权人现金净流量] F060901C [筹资活动债权人现金净流量TTM] F061001B [筹资活动股东现金净流量] F061001C [筹资活动股东现金净流量TTM] F061201B [折旧摊销] F061201C [折旧摊销TTM] F061301B [公司现金流1] F061302B [公司现金流2] F061301C [公司现金流TTM1] F061302C [公司现金流TTM2] F061401B [股权现金流1] F061402B [股权现金流2] F061401C [股权现金流TTM1] F061402C [股权现金流TTM2] F061501B [公司自由现金流(原有)] F061601B [股权自由现金流(原有)] F061701B [全部现金回收率] F061801B [营运指数] F061901B [资本支出与折旧摊销比] F062001B [现金适合比率] F062101B [现金再投资比率] F062201B [现金满足投资比率] F062301B [股权自由现金流] F062401B [企业自由现金流] Indcd1 [行业代码1] Indnme1 [行业名称1] 季度数据,所有沪深北上市公司的 分别包含excel、dta数据文件格式及其说明,便于不同软件工具对数据的分析应用 数据来源:基于上市公司年报及公告数据整理,或相关证券交易所、各部委、省、市数据 数据范围:基于沪深北证上市公司 A股(主板、中小企业板、创业板、科创板等)数据整理计算
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值