字符串模式匹配

来源:互联网 发布:看网络直播要钱吗 编辑:程序博客网 时间:2024/06/17 15:08
这两天随便翻了翻算法导论,无意看到了模式匹配一章节,由于在本科上数据结构时也学过一点,但是记得老师那时说模式匹配也不做硬性要求(要链表,栈,队列)不会考试,考研也不会考,所以就没有花很多时间看相应的算法;现在看到了这了,有点兴趣所以看了看,并用代码实现。
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 stubString 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);//先得到nextwhile(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));elseSystem.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;}}


 

原创粉丝点击