KMP算法java代码实现

本文详细介绍了KMP算法的工作原理,通过一个示例展示了如何在长字符串中查找短字符串的出现位置。KMP算法利用前缀和后缀的概念,通过构建前缀数组优化匹配过程,避免不必要的字符比较,提高查找效率。代码实现中包含了获取前缀数组、构造next数组以及主要的KMP搜索方法。
摘要由CSDN通过智能技术生成

简单用图了解一下KMP算法

KMP算法是字符查找算法,假设有两个字符串,Text和Partterns,检查Text中是否存在partterns,用的KMP算法。

此算法用到 前缀和后缀的概念,具体如下:

 上代码

/**
 * KMP算法
 * @author SuMalago
 *
 */
public class KMPCalculator {
	
	public static void main(String[] args) {
		String partterns = "ABDCABDA";
		String text = "ABDCADAAABDCABDADDABDCABDA";
		KMPSearch(text,partterns);
		
	}
	
	/**
	 * @param textStr 长字符串
	 * @param partterns 短字符串
	 */
	
	public static void KMPSearch(String textStr,String partterns){
		char[] parttern = partterns.toCharArray();
		int pLen = parttern.length;
		int[] next = getNextArray(prefixArray(parttern,pLen));
		int p = 0;//用来循环parttern	  方便好记取首字母p	
		
		char[] text = textStr.toCharArray();
		int tLen = text.length;
		int t = 0;//用来循环text 方便好记取首字母t
		
		while(t<tLen){
			//这里是最后一步,走到最后parttern检查完了,且最后的位置下的字符也相同
			if(p == pLen-1 && parttern[p] == text[t]){
				System.out.println(" parttern is index of :"+ (t-p));
				p=next[p];
			}
			
			if(parttern[p] == text[t]){//匹配到 继续循环走下一个
				p++;t++;//两个都后移
			}else{
				//使用next下的下标p的值(此值是前面的,肯定next[p] <= p)进行匹配,
				//然后再匹配时,后面的都整体后移了
				p = next[p]; //拿到新的p值后,需要再次判断parttern[p]和text[t],相同就俩都后移,不同就继续查询next。不能t++
				if(p == -1){//取到第一个了
					p++;t++;
				}
			}
		}
	}

	/**
	 * 取出 prefix数组
	 * @param parttern 需要求出前缀重复的str,len是parttern长度
	 * @return
	 */
	public static int[] prefixArray(char[] parttern,int len){
		//前缀数组
		int[] prefix = new int[len];
		int n=0;
		prefix[0] = 0;
		for(int i=1;i<len;i++){
			//取出当前位置 i-1 存储的prefix值
			n = prefix[i-1];
			if(parttern[i] == parttern[n]){
				n++;
			}else if(parttern[i] ==parttern[0]){
				//如果和前面的prefix存储的值不一样了,看看和第一个是不是一样
				n=1;
			}else{
				n=0;
			}
			prefix[i] = n;
		}
		
		return prefix;
	}
	
	/**
	 * 这个方法就是把prefix数组都后移一位,第一位下标是0的补上-1
	 * @param prefix
	 * @return
	 */
	public static int[] getNextArray(int[] prefix){
		int[] next = new int[prefix.length];
		next[0] = -1;
		for(int i=0;i<prefix.length;i++){
			if(i<prefix.length-1){
				next[i+1] = prefix[i];
			}
		}
		return next;
	}
	
}

 

 

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值