KMP算法

package demo2;

public class P83 {
//KMP算法
//思路:减少回退。
//主串s,模式串p;指针i、j分别指向s、p来比较。
//假设有两个模式串,p1在j失配,说明前面0~(j-1)与s相同,这段中p1的后缀与p2的前缀重合部分免检(这部分p2等于p1等于s)。
//易得,公共前后缀与s无关,可以由p本身得到。算出跳转位置构成next数组,j=next[j],后一个j为失配位置
public static void main(String[] args) {
String s="babaabbabc";
String p="babc";
System.out.println(kmp(s, p));
}

static int[] next(String p) {
	int pLen=p.length();
	int[] next=new int[pLen];
	char[] pArr=p.toCharArray();
	
	next[0]=-1;		//-1是为了处理这一要i++的特殊情况
	if(pLen==1)
		return next;
	next[1]=0;
	
	int j=1;		//递推法,求之后的next[]
	//原理:next[j]等于k,就是j处失配后有k长度的公共前后缀。
	int k=next[j];
	while(j<pLen-1) {
	//若j、k的字符相同,则(j+1)处失配的公共前后缀为k+1
		if(k<0 || pArr[j]==pArr[k]) {
			next[++j]=++k;
		}
	//若不同,则next[j]的值k不可用,继续找相同字符
		else {
			k=next[k];
		}
	}
	
	return next;
}

static int kmp(String s,String p) {
	int[] next=next(p);
	int i=0;
	int j=0;
	int sLen=s.length();
	int pLen=p.length();
	
	while(i<sLen) {
		if(j==-1 || s.charAt(i)==p.charAt(j)) {
			i++;
			j++;
		}
		else {
			j=next[j];
		}
		
		if(j==pLen) {		//匹配成功,此时i、j在结尾的再后一位
			return i-pLen;
		}
	}
	return -1;		//找不到
}

}

posted @   fighterk  阅读(22)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· AI 智能体引爆开源社区「GitHub 热点速览」
· 三行代码完成国际化适配,妙~啊~
· .NET Core 中如何实现缓存的预热?
点击右上角即可分享
微信分享提示