KMP、BM、Sunday等字符串匹配算法及实现

原创 2016年08月28日 18:25:20

发现字符串的匹配完全要考虑全面,如果考虑的情况不足够全面,就很可能出现这个例子可以运行,下一个例子的就行不通,毕竟匹配可能遇到各种各样的情况。本着可以实现效果就可以的原则,编的代码也实在是不优美,BM参考了别人的代码,因为写的精炼,按照自己的思路来写,然后发现有的可以运行,有的就达不到相应的效果。主要实现了暴力字符串匹配、KMP、BM、Sunday四种,几天的时间学习完的,回头再看的时候发现自己都有点忘记了,赶紧记下来~

暴力字符串匹配,效率比较低,因为对主串来说,模式串每次移动的位置都为一个单位。而其它的,KMP、BM、Sunday则是按照自己的原则尽可能的增大移动的位数。下面针对KMP、BM、Sunday简单的介绍

KMP

KMP主要是利用模式串本身的特点来计算出NEXT值,模式串中的每一个字符都有一个NEXT值,NEXT为整型数组,比如NEXT[i]就代表在模式串的第i个位置的部分匹配值,其实就是模式串和主串最后一个匹配位置的部分匹配值,i+1个位置两个串就不匹配了。利用已经匹配的长度减去部分匹配值就可以得到模式串的移动位数。其实大白话就是现在主串匹配的子串在模式串中是否还存在,在计算NEXT值时则是利用已经匹配模式串的前缀和后缀,求前缀和后缀的最大长度。NEXT值下标是从1开始的

文章http://blog.csdn.net/buaa_shang/article/details/9907183

public class KMP {

	
	public static void main(String[] args) {
		/*String str = "ababc";
		String orig ="abababc";*/
		String str = "abaabcac";
		String orig ="abcabaaabaabcac";
		/*String str = "aba";
		String orig ="aba";*/
		int[] next = get_Next(str);
		for(int i=0;i<str.length()+1;i++){
			System.out.print(next[i]);
		}
		System.out.println();
		KMP.search(orig, str, next);

	}
	//next[j]表示在当前模式串到T[j]遇到失配的情况,在模式串中重新和主串匹配的位置
	public static int[] get_Next(String str){
		
		//对str求出各个字符位置的部分匹配值
		int[] next = new int[str.length()+1];
		int j=0;
		next[0]=next[1]=0;
		for(int i=1;i<str.length();i++){
			while(j>0&&str.charAt(j)!=str.charAt(i))
				j=next[j];
			if(str.charAt(i)==str.charAt(j))j++;
			next[i+1]=j;
		}
		
		return next;
		
		
		
	}
	//orig为主串,而find为模式串,查找匹配位置以及匹配长度
	public static void search(String orig,String find,int[]next){
		int j=0;
		for(int i=0;i<orig.length();i++){
			while(j>0&&orig.charAt(i)!=find.charAt(j))
				j = next[j];
				if(orig.charAt(i)==find.charAt(j)){
					j++;
				}
				if(j==find.length()){
					System.out.println("find at position " + (i - j+1));  
		            System.out.println(orig.subSequence(i - j + 1, i + 1));  
		            j = next[j]; 
				
				
			}
			
		}
		
	}
BM,BM提出了坏字符和好后缀的概念,并提出了坏字符原则和好后缀原则,选择两种原则下移动位数最大的作为移动位数

文章http://blog.csdn.net/appleprince88/article/details/11881323

public class BM {

	public static void main(String[] args) {
		
		String str="exex";
		String text ="exaxexex";
		int[] suffix=new int[5];
		BM.suffix(str, 4, suffix);
		for(int i=0;i<suffix.length;i++){
			System.out.print(suffix[i]);
		}
		int[] bmgs = new int[5];
		BM.preBmGs(str, 4, bmgs);
		BM.boyerMoore(str , text);
	}
	//会用到两个数组,一个是依照坏字符规则得到的应该的移位数
	//另一个则是依照好后缀规则得到的应该的移位数
	//map中存放的是模式串中的各个字符,以及字符在模式串中倒叙的索引
	private static void preBmBc(String pattern,Map<String,Integer>bmbc){
		for(int i=pattern.length()-2;i>=0;i--){
			if(!bmbc.containsKey(pattern.charAt(i))){
				bmbc.put(pattern.charAt(i)+"", pattern.length()-i-1);
			}
		}
		
	}
	//如果存在则返回值,如果不存在则返回模式串的长度,不是应该返回-1么
	private static int getBmBc(String c,Map<String,Integer>bmbc,int m){
		if(bmbc.containsKey(c)){
			return bmbc.get(c);
		}
		else
		return m;
		
	}
	public static void suffix(String pattern,int length,int[]suffix){
		
		suffix[length-1]=length;
		int q;
		for(int i=length-2;i>=0;i--){
			q = i;
			 while(q>=0&&pattern.charAt(q)==pattern.charAt(length-1-i+q))  
	            {  
	                q--;  
	            }  
	            suffix[i]=i-q; 
		}
		
	}
	
	public static void preBmGs(String pattern,int length,int[] bmgs){
		//主要从字符串的三个方面来进行
		//没有子串匹配上好后缀,也找不到一个后缀 EXAMPLE
		      //                           ######MPLE
		//没有子串匹配上好后缀,单可以找到一个最大后缀  EXAMPLE
	      //                                    #PLE###MPLE
		//模式串中有子串匹配上好后缀                                            EXAMPLE
	      //                                  #MPLE###MPLE
		//先去处理一下模式串的后缀匹配情况
		int[] suffix= new int[length];
		int i,j;
		suffix(pattern,length,suffix);
		for(i=0;i<length;i++){
			bmgs[i] = length;
		}
		j=0;
		for(i=length-1;i>=0;i--){
			if(suffix[i]==i+1){
				for(;j<length-1-i;j++){
					if(bmgs[j]==length){
						bmgs[j]=length-i-1;
					}
					
				}
			}
		}
		 for(i=0;i<length-1;i++)  
	        {  
	            bmgs[length-1-suffix[i]]=length-1-i;  
	        } 
		 System.out.print("bmgs:");
		 for(int k=0;k<length;k++){
			 System.out.print(bmgs[k]);
		 }
		 System.out.println();
		
	}
	public static void boyerMoore(String pattern,String text){
		int m = pattern.length();
		int n = text.length();
		Map<String,Integer> bmBc= new HashMap<String,Integer>();
		int[] bmGs = new int[m];
		preBmBc(pattern,bmBc);
		preBmGs(pattern,m,bmGs);
		int i=0;
		int j=0;
		int count=0;
		while(j<=n-m)  
        {  
            for(i=m-1;i>=0&&pattern.charAt(i)==text.charAt(i+j);i--)  
            {   //用于计数  
                count++;  
            }         
            if(i<0){  
                System.out.println("one position is:"+j);  
                j+=bmGs[0];  
            }else{  
                j+=Math.max(bmGs[i],getBmBc(String.valueOf(text.charAt(i+j)),bmBc,m)-m+1+i);  
            }  
        }  
        System.out.println("count:"+count);  
    }  
	}

Sunday,从左向右进行比较,移动的位数则是从模式串相对于主串位置的下一个位置的字符是否能在模式串中找到,如果能找到,则秉着移动模式串使得模式串的相同的字符与主串该字符对齐的原则进行移动,否则则跳过,也就是说模式串的首字符要移动到该字符的下一个位置。

public class Sunday {

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		/*String pattern = "bfde";
		String text ="abcdebfdem";*/
		/*String pattern ="mck";
		String text = "abcdemcklm";*/
		String pattern ="del";
		String text = "decmendels";
		
		System.out.print("模式串在主串的起始索引为:"+Sunday.sunday(pattern, text));

	}
	private static int getLocation(String pattern,String text,int length){
		//判断在text中的length位置的字符是否在pattern中存在,如果存在,则返回,找不到
		//则返回-1;
		int i=pattern.length()-1;
		while(i>=0&&pattern.charAt(i)!=text.charAt(length))
			i--;
		return i;
		
	}
	public static int sunday(String pattern,String text){
		int i=0;
		int j=0;
		
		int dcount=0;//用count来记录从左向右匹配的字符数
		int location =0;
		boolean flag=false;
		while(i<text.length()&&!flag){
			j=0;
		    dcount =0;
		    flag = false;
		    System.out.print(i);
			while(!flag&&j<pattern.length()&&i<text.length()&&text.charAt(i)==pattern.charAt(j)){
				dcount++;
				if(dcount==pattern.length()){
					flag=true;
					System.out.print("i"+i);
					break;
				}
				i++;
				j++;
				
			}
			
			if(j<pattern.length()&&i<text.length()&&text.charAt(i)!=pattern.charAt(j)){
				location = getLocation(pattern,text,pattern.length()+i-dcount); 
				if(location!=-1)
				{i =i+pattern.length()-dcount-location;}
				else{
					i=i+pattern.length()+1-dcount;
			
				}
			}
			
			
		}
		return i-pattern.length()+1;
		
	}
	

}

暴力字符串匹配

public class Match1 {

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		String string = "abcdefg";
		String str = "cde";
		System.out.print(MessageFormat.format("模式串在主串第{0}位置开始匹配,结束匹配位置为{1}", Match1.stringMatch(string, str),Match1.stringMatch(string, str)+str.length()-1));

	}
	public static int stringMatch(String string,String str){
		//string 为主串,str为模式串
		boolean flag = false;
		int index =0;
		/*System.out.print(string.length());*/
		for(int i=0;i<string.length();i++){
			 index=i;
			flag = true;
			for(int j=0;j<str.length()&&flag;j++){
				if(string.charAt(i)!=str.charAt(j)){
					flag = false;
					
				}else{
					i++;
					flag = true;
					
					
				}
			}
			if(flag){
				break;
			}
			
			
		}
		
		return index;
	}
	

}

字符串的匹配各种计算长度,计算位置,计算是否匹配,有的时候还要一直循环循环,设置一个标识符有时候还是蛮必要的。

版权声明:本文为博主原创文章,未经博主允许不得转载。

相关文章推荐

字符串匹配算法综述:BF、RK、KMP、BM、Sunday

字符串匹配算法综述:BF、RK、KMP、BM、Sunday

sunday、kmp、 bm、 horspool字符串匹配算法 code

kmp bm字符串匹配算法代码实现 #include #include #include // 失配时,pat的下一跳位置(pat = "abab"; value[] = {-1, 0, -1...

字符串模式匹配算法——BM、Horspool、Sunday、KMP、KR、AC算法一网打尽

字符串模式匹配算法——BM、Horspool、Sunday、KMP、KR、AC算法一网打尽     本文内容框架: §1 Boyer-Moore算法 §2 Horspoo...
  • Aiphis
  • Aiphis
  • 2015年07月28日 15:17
  • 292

字符串模式匹配算法——BM、Horspool、Sunday、KMP、KR、AC算法一网打尽

from : http://dsqiu.iteye.com/blog/1700312 字符串模式匹配算法——BM、Horspool、Sunday、KMP、KR、AC算法一网打尽 ...

字符串模式匹配算法——BM、Horspool、Sunday、KMP、KR、AC算法一网打尽

字符串模式匹配算法——BM、Horspool、Sunday、KMP、KR、AC算法一网打尽     本文内容框架: §1 Boyer-Moore算法 §2 Horspoo...
  • fghydx
  • fghydx
  • 2014年03月04日 14:55
  • 816

字符串模式匹配算法——BM、Horspool、Sunday、KMP、KR、AC算法

字符串模式匹配算法——BM、Horspool、Sunday、KMP、KR、AC算法一网打尽     本文内容框架: §1 Boyer-Moore算法 §2 Horspoo...
  • mitesi
  • mitesi
  • 2014年04月18日 22:47
  • 829

字符串匹配算法---Brute force、KMP、Sunday

字符串匹配---输入原字符串(String)和子串(又称模式),输出为子串在原字符串中的首次出现的位置。在这儿,我们介绍用于字符串匹配的Brute force、KMP和Sunday方法。 1.Bru...

Sunday字符串匹配算法的效率改进

  • 2015年05月04日 19:50
  • 1.64MB
  • 下载

字符串匹配算法之___Sunday算法的java实现

Sunday算法的java实现 Sunnday算法简介 一个示例 java实现 Sunday算法简介 Sunday算法是Daniel M.Sunday于1990年提出的字符串模式匹配。其核心思想是...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:KMP、BM、Sunday等字符串匹配算法及实现
举报原因:
原因补充:

(最多只允许输入30个字)