KMP模式匹配算法--未優化

字符串的比配是一個很重要的點,去年參加校園招聘的時候考了這個,今天翻開以前的教程看到了KMP,就總結一下吧,其思想還是挺好的。

對於字符串匹配,最簡單、最笨、最低效的方法就是循環匹配,也就是:從主串的第一個字符開始,依次與字串進行比較,即把主串的每一個字符當作字串的首字符,直到匹配成功或者遍歷完主串(失敗)。

可想而知其中包含了很多冗餘的操作,因爲某次匹配失敗便要回滾主串到上次開始的下一個字符,開始下一輪匹配,然而有些回滾是不需要的,如:

1,字串中沒有重複字符的時候:

主串:efgrabcdefgadad       用i循環

字串:efga                              用j循環

第一輪匹配(i=0):當i循環到3(主串的r位置)時,匹配失敗(r和a不相同),便要開始下一輪匹配,即i回滾到1,j回滾到0

觀察字串可以發現,e和後面的所有字符都不相同,同樣,字串的e和主串的fg也不相同,所以不比較知道不相同,所以第二輪和第三輪比較可以直接跳過,即i不需要回滾

即下一輪比較只需要從i不變,j變爲0開始;

2,字串中有重複字符的時候:

主串:abdfgabefaexababdfgabxggadad       用i循環

字串:abdfgabx                                                  用j循環

可以知道,第一輪匹配失敗後,因爲字串的a和bdfg都不相同,所以都不用比較,而ab和ab相同,不比較也知道,所以也不需要比較,所以下一輪比較只需要把j回滾到d的位置開始匹配即可,I不需要回滾;

從上面的分許可以看出,無論字串有沒有重複,i都不需要回滾,只需要回滾j,而且重複和不重複的時候j的回滾是不相同的。

以上就是KMP算法的思想,旨在消除不必要的回滾,其最重要的就是next()方法(用於求出j下一次需要回滾到的位置)


例子:

1,main方法:

      public static void main(String[] args) {

       String sub = "abefr";
       String str = "dfabfeabefrfef";
       int[] next = next(sub);
       pattern(str,sub,next);
       

   }

輸出:6

2,next()方法:
public static int[] next(String sub) {
         int[] next = new int[sub.length()];
         char[] subs = sub.toCharArray();
         int length = sub.length();
         
         int i,j;
         next[0] = -1;
         i = 0;
         for(j = 1;j < length;j++) {
            i = next[j - 1];
            while(i >= 0 && subs[j] != subs[i+1]) {
                i = next[i];    
            }
            
           if(subs[j] == subs[i+1]) {
          next[j] = i+1;
           }
           else {
          next[j] = -1;
           }
         }
         return next;

    }


3,匹配方法:
    public static void pattern(String str,String sub,int[] next) {
        char[] ch1 = str.toCharArray();
        char[] ch2 = sub.toCharArray();
        int i = 0,j = 0;  //i控制ch1,j控制ch2;
        for(;i < ch1.length; ) {
            if(ch1[i] == ch2[j]) {//匹配就自動遞增,往後匹配。
                if(j == ch2.length-1) {
                    System.out.println(i-ch2.length+1);
                    break;
                }
                j++;
                i++;
            }
            else if(j == 0) {
                 i++;
            }
            else {
                j = next[j-1]+1;
            }
        }
    }
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章