kmp模式匹配

来源:互联网 发布:日租卡流量监控软件 编辑:程序博客网 时间:2024/06/01 23:08

朴素的模式匹配算法,是将子串与主串匹配,如果发生不匹配,则子串下标退回到原点,主串下标加1,从头开始匹配。这样的算法简单易懂,但进行了很多次无用的匹配,时间复杂度为O(m*n)。

而KMP模式匹配在朴素的模式匹配上加以改进,省略掉了很多的重复的比较过程,例如主串为abbabbe,子串为abbe

kmp模式匹配就是这样通过检查子串中的后缀是否与前缀相匹配的方法,确定子串回溯的位置,这样就能省去很多次无用的匹配,优化了算法。

于是问题的关键变成了怎样找到子串应该回溯的位置。子串回溯的位置只有子串的结构有关,子串的每一个位置都有一个回溯值,当子串与主串再此发生不匹配时,子串就回溯到该位置。定义该回溯数组为next【】。

ok,i think you must want to say shut your mouth and show me the code.

//      该方法用来寻找子串的next[]数组public static int [] getnext(String T){//      j表示子串中的下标    int j = 1;//      k表示前缀与子串后缀相匹配的最大值    int k = 0;    int [] next = new int[T.length()];//      初始化next[0]=-1,next[1]=0    next[0] = -1;    next[1] = 0;    while(j<T.length()-1)    {//          如果前缀等于后缀,next[j+1]=k+1        if(T.charAt(j)==T.charAt(k))        {            next[j+1] = k+1;            j++;            k++;        }        else if (k == 0)         {            next[j+1] = 0;            j++;        }//          如果不匹配,k值回溯。相当于子串中进行一次模式匹配        else            k = next[k];    }//      此处用来验证next[]数组是否正确//      for (int z = 0; z < next.length; z++) {//          System.out.print(next[z]);//      }    return next;}

在得到next[]数组后,即可进行kmp模式匹配

//  实现kmp模式匹配public static int kmp_index(String s,String t) {    int i = 0;    int j = 0;//      获得next[]数组    int next[] = getnext(t);    while (i<s.length()&&j<t.length()) {        if (j == -1||s.charAt(i) == t.charAt(j)) {            i++;            j++;        }//          如果不匹配,j回溯至当前j值的next[j]处        else {            j = next[j];        }    }    if (j == t.length()) {        return i-t.length();    }    else {        return -1;    }}//  测试kmp模式匹配//  public static void main (String [] args) {//      String string1 = "aaabbbaaab";//      String string2 = "bbbaaa";//      getnext(string2);//      int i = kmp_index(string1, string2);//      System.out.println(i);//  }}
0 0