字符串模式匹配

这两天随便翻了翻算法导论,无意看到了模式匹配一章节,由于在本科上数据结构时也学过一点,但是记得老师那时说模式匹配也不做硬性要求(要链表,栈,队列)不会考试,考研也不会考,所以就没有花很多时间看相应的算法;现在看到了这了,有点兴趣所以看了看,并用代码实现。
BF算法和KMP算法比较:
BF算法思路:字串和母串中的字符比较相等时,均后移,否则母串开始比较的位置会移至到上次开始比较的下个位置,字串则移至0位置;如此循环。时间复杂度O(n*m).
KMP算法思路:由于BF算法的缺点(每次不等时,母串均要前移,根据字串的结构可以发现其实母串前移,会做很多无用的比较),所以KMP算法采用当不等时,母串不移动,字串向右移,而具体移多少,移到什么位置,就是本算法的难点即求next[m]的值;(这个next[m]值在此就不详细说明,可以看很多牛人的博客,都介绍的很详细,或者直接看数据结构那本经典的书,上面介绍的很详细)。时间复杂度O(n+m).
 
 
package test;

import java.util.ArrayList;

//如何找到所有的位置
public class ModelMatch {

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		
		String T="acabaabaabcacaabc";
		String S="abaabcac";
		//System.out.println(T);
		//for(int i=0;i<str.length();++i)
		    //System.out.println(str.charAt(i));
		System.out.println("======采用BF算法========");
		int k=index(T,S,0);
	
		if(k!=-1)
			System.out.println("\n匹配成功 k:"+k+"\n======================\n");
		else 
			System.out.println("匹配不成功!"+"\n======================\n");
		
		System.out.println("\n======采用KMP算法========");
		int kmp=indexKMP(T,S,0);
		if(kmp!=-1)
			System.out.println("\n匹配成功kmp:"+kmp+"\n======================");
		else
		    System.out.println("没有找到!"+"\n======================");
		
		int[] a=indexAll(T,S,0); //求所有模式串的出现的位置
		System.out.println("所有出现的位置:");
		for(int rep:a){
			System.out.println(rep);
		}
 
	}
	
	//采用KMP算法
	static int indexKMP(String T,String S,int pos){
		int[] next=new int[S.length()];
		int i=pos,j=0,jf=0;
		boolean flag=false;
		int count=1;
		System.out.println("第"+count+"趟比较");
		System.out.println(T);
		System.out.print(S.charAt(0));
		
		getNext(S,next);//先得到next
		
		while(i<T.length() && j<S.length()){
			if(j==-1 || T.charAt(i)==S.charAt(j)){
				if(j!=-1){
					jf=j+1;
					jf=i+1-jf;
				}
				++i;++j;flag=true;
			}
			else{
				flag=false;
				
				j=next[j];
				jf=i-j;
				count++;
			}
			if(j<S.length()){
				if(flag==true){
					System.out.println("\n"+T+" 字符比较相等,均后移  "+" T中 i移至:"+i+",S中 j移至:"+j);
				}
				else{
					System.out.println("\n"+"第"+count+"趟比较");
					if(j==-1)
						System.out.println(T+" 其中next["+(j+1)+"]="+j+" 所以"+"  S串j移至:"+(j+1)+", T串i也后移为:"+(i+1));
					else
						System.out.println(T+",next["+jf+"]="+j+" 不相等,T串i位置不变为:"+i+", S串j移至:"+j);
				}
				for(int k=0;k<jf;k++){
					System.out.print(" ");
				}
				for(int k=0;k<=j;k++){
					System.out.print(S.charAt(k));
				}
			}
			
			
		}
		if(j>=S.length())
			return i-j;
		else
		    return -1;
	}
	//求next值
    static void getNext(String S,int[] next){
    	int i=0;
    	int j=-1;
    	next[0]=-1;
    	while(i<S.length()-1){
    		if(j==-1 || S.charAt(i)==S.charAt(j)){
    			++i;++j;next[i]=j;
    		}
    		else j=next[j];
    	}
    }
	//
	static int index(String T,String S,int pos){
		int i=pos,j=0,start=0;
		boolean flag=false;
		int count=1;
		System.out.println("第"+count+"趟比较");
		System.out.println(T);
		System.out.print(S.charAt(0));
		while(j<S.length() && i<T.length()){
			
			if(T.charAt(i)==S.charAt(j)){
				++i;++j;flag=true;
			}
			else{
				i=i-j+1;
				start=i;//标记开始比较时i值,以便模式串可以向后移动start个空格
				j=0;    //顺序不能颠倒
				flag=false;
				count++;
			} 
			
			if(j<S.length()){
				if(flag==true){
					System.out.println("\n"+T+" 字符比较相等,均后移"+"T中 i移至:"+i+",S中 j移至:"+j);
				}
				else{
					System.out.println("\n"+"第"+count+"趟比较");
					System.out.println(T+" 字符比较不相等,T中 i移至:"+start+",S中 j移至:"+j);
				}
					
				
				for(int k=0;k<start;k++){
					System.out.print(" ");
				}
				for(int k=0;k<=j;k++){
					System.out.print(S.charAt(k));
				}
			}
			
		}
		
		//System.out.println(j);
		if(j>=S.length())
			return i-j;
		else 
			return -1;
	}
	
	
	static int[] indexAll(String T,String S,int pos){
		int i=pos,j=0;
		ArrayList<String> list=new ArrayList<String>();
		while(i<T.length()){
			if(T.charAt(i)==S.charAt(j)){
				++i;++j;
			}
			else{
				i=i-j+1;
				j=0;    //顺序不能颠倒
			} 	
			if(j>=S.length()){
				//System.out.println(i-j);
				list.add(String.valueOf(i-j));
				++i;
				j=0;
			}
		}
		//System.out.println(j);
		int[] a=new int[list.size()];
		for(int k=0;k<list.size();k++){
			a[k]=Integer.parseInt(list.get(k));
		}
		return a;
	}
}


 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值