1. 程式人生 > >資料結構——串—串的模式匹配演算法

資料結構——串—串的模式匹配演算法

        要找到模式串在主串中的位置,最簡單的方法就是一位一位的排查,如果相同,則比較下一項是否相同,一旦出現不同的字元,將剛剛匹配模式串主串的第一位向後移動一位繼續比較,這樣的演算法在某些串中可能會出現多次回溯,所以針對模式串的特點出現了一種改進——演算法KMP演算法

下面給出其程式碼實現:

import java.util.Scanner;
/*
 j=0只能在上一次迴圈中j=1且字元不符合時產生,說明模式串和主串第一位不符,此時應將i、j加1,主串從下一位開始,因為j加1後是1,模式串還是從第一位開始
 所以把next[1]設為0,保證了保證了過程與字元符合的情況相同,減少了一種情況
 當字元相等時,i、j加1;
 當字元不符合時,j賦予next[j],表示了模式串的j位與主串i位不符合時,從模式串的next[j]重新開始比較,主串位置不變
 */
public class KMPIndex {
	int getIndex(String s,String t,int pos,int[] next)//在主串s的pos個字元之後查詢模式串t的位置(第一個字元)pos在1到s.length()-t.length()之間
	{
		char ss[]=s.toCharArray();//先將字串轉化為陣列,便於對下標進行操作
		char tt[]=t.toCharArray();
		int i=pos-1;
		int j=1;//
		while(i<s.length()&&j<=t.length())
		{
			if(j==0||ss[i]==tt[j-1])//j==0表示兩個串字元符合,都往後移動一位
			{
				i++;
				j++;
			}
			else j=next[j];//如果不符合,回到指定位置重新開始匹配
		}
		if(j==t.length()+1)
			return i-t.length()+1;
		else 
			return -1;
	}
/*
 首先將next[1]等於0,i=1指向模式串第1位,與模式串j=0開始比較,
 如果j是0;
 對於第一次迴圈,i、j均加1,將next[2]指向第一位;
 如果不是第一次迴圈,只能在上一次迴圈中j=1且字元不符合時產生,說明i對應字元與模式串第一位字元不相同,
 此時應將i、j加1,next[i]=j;因為j加1後是1,表示一位的next指向第一位,表示下一位不符合時,直接從頭開始比較,中間不存在可能的序列
相等時,將i、j加1,next[i]=j;表示下一位的next指向模式串的第j位,表示可以直接從第j位開始比較;
 */


	int[] getNext(String s)//模式串的next函式
	{
		int[] next=new int[s.length()+1];
		char sss[]=s.toCharArray();
		char[] ss=new char[s.length()+1];
		for(int i=1;i<s.length()+1;i++)//ss陣列從1開始儲存
			ss[i]=sss[i-1];
		int i=1;
		int j=0;
		next[1]=0;
		while(i<s.length())
		{
			if(j==0||ss[i]==ss[j])//若j是0,表示需要重新匹配 
			{
				i++;
				j++;
				next[i]=j;//把下一位的next定為下一個與之比較的項
			}
			else j=next[j];
		}
		return next;
	}
	public static void main(String[] args)
	{
		int index,pos;
		KMPIndex exp;
		exp=new KMPIndex();
		String s=new String();
		String t=new String();
		Scanner scan=new Scanner(System.in);
		System.out.print("請輸入主串:");
		s=scan.nextLine();
		System.out.print("請輸入模式串:");
		t=scan.nextLine();
		System.out.print("請輸入起始位置:");
		pos=scan.nextInt();
		
		int next[]=new int[t.length()];
		next=exp.getNext(t);
		index=exp.getIndex(s, t, pos, next);
		if(index!=-1)
		System.out.print("已找到匹配子串,位置為"+index);
		else System.out.print("未找到匹配子串");
	}
}