字符串模式匹配算法包括三种:蛮力方式,BM模式匹配,KMP模式匹配
蛮力方式容易理解,比较方向从左往右逐个比较,最坏时间复杂度可达O(m·n)(m为 模式字符串长度,n为源字符串长度),最好时间复杂度O(m).
BM模式匹配采用了两个启发式原则:坏字符和好后缀原则,从而避免一些不必要的比较
最坏时间复杂度为O(m·n),最好时间复杂度为O(n/m).
附BM模式匹配代码
/** * BoyerBoomer算法查找 * @param src 源字符串 * @param dst 模式字符串 * @return int 匹配成功返回1,失败返回0 */ public static int BoyerBoomerMatchPractice(String src,String dst) { int srclength=src.length(); int dstlength=dst.length(); int s=dstlength-1,d=dstlength-1; int srcs=dst.length()-1; while(srcs<=srclength-1) {//双循环,当循环到源字符串末尾时结束循环 while(d>=0) {//根据模式字符串进行循环判定 if(src.charAt(s)==dst.charAt(d)) { s-=1;//若相等从右向左逐步移动一位 d-=1; } else { int temp=last(dst,src,d,s);//判定移动函数,分为坏字符和最好后缀两种情况 srcs+=temp; System.out.println("fdsfsdf " +src.substring(0,srcs)+" "+temp+" srcs"+srcs); s=srcs; d=dstlength-1; break; } } System.out.println(" "+d); if(d==-1) return 1; } return 0; } /** * 获得移动的步数 * @param dst 模式字符串 * @param src 源字符串 * @param d 模式字符串已匹配的计数 * @param ssss 源字符串中不匹配的计数 * @return 移动的步数 */ public static int last(String dst,String src,int d,int ssss) { //首先判定是否为坏字符 if(d==dst.length()-1) {//是 char lastchar=src.charAt(ssss); System.out.println("lastchar"+lastchar+" "+ssss); //判定字符是否在模式字符串当中存在 int i; for(i=0;i<=dst.length()-1;i++) if(lastchar==dst.charAt(i)) break; if(i==dst.length()) { System.out.println(1+"坏字符"); return 1; } else { System.out.println((d-i)+"坏字符else"+"d "+d+ "i "+i); return d-i; } } else {//否,找好后缀 String goodend=dst.substring(d+1,dst.length());//获得好后缀 return isexitst(dst,goodend); } } /** * 当模式字符串当中不存在好后缀时,获得移动的步数 * @param dst 模式字符串 * @param goodend 好后缀 * @return 移动的步数 */ public static int isexitst(String dst,String goodend){ int s=dst.length()-2;//跳过最后一个字符 int ss=dst.length()-2; int d=goodend.length()-1; while(s>=d) {//采用蛮力方式来判断模式字符串当中是否存在好后缀 while(d>=0) { if(dst.charAt(s)==goodend.charAt(d)) { s-=1; d-=1; } else { ss-=1; s=ss; d=goodend.length()-1; break; } } if(d==-1) { System.out.println("存在好后缀 "+(dst.length()-(s+1+goodend.length()))); return dst.length()-(s+1+goodend.length()); } }//不存在好后缀 //就寻找最好的最前缀 int dtime=d; int ds=0;//位置 String sgoodend=goodend; while(dtime>=0) {//按照后缀从前往后逐步减一进行判断 if(dst.startsWith(sgoodend)){ System.out.println("最好的最前缀 "+(dst.length()-sgoodend.length())); return dst.length()-sgoodend.length();} else { ds+=1; sgoodend=goodend.substring(ds,goodend.length()); } dtime-=1; } return 1; }