比BF算法改進的地方在:每一趟匹配出現字符不等時,不需回溯指針i,而是利用已經獲得的「部分匹配」的結果,將模式T向右滑儘量遠後,繼續進行比較。java
須要計算next函數值:算法
比較T[j-1]與T[k]的值,函數
a. 若T[j-1]等於T[k],則next[j]=k+1。b. 若T[j-1]不等於T[k],令k=next[k],若k等於-1,則next[j]=0,不然跳至3。spa
1 import java.util.Scanner; 2 3 public class KMP { 4 public static void main(String[] args) { 5 menu(); 6 Scanner scan= new Scanner(System.in); 7 String S=scan.next(); 8 String T=scan.next(); 9 System.out.println("輸入完畢,算法運行結果以下:"); 10 System.out.println("主串S:"+S+" 模式T:"+T); 11 scan.close(); 12 char[] charS=S.toCharArray(); 13 char[] charT=T.toCharArray(); 14 int pos=1; 15 int next[] = new int[charT.length+1]; 16 int nextval[] = new int[charT.length+1]; 17 getNext(charT,next); 18 getNextval(charT,nextval); 19 run(charS,charT,pos,nextval); 20 } 21 public static void menu() { 22 System.out.println("串的模式匹配算法——KMP算法\n"); 23 System.out.println("請在如下分別輸入主串S,和須要匹配的模式T:"); 24 } 25 public static void getNextval(char[] charT,int nextval[]) { 26 int i=1; 27 int j=0; 28 nextval[0]=-1; 29 nextval[1]=0; 30 while(i<charT.length) 31 { 32 if(j==0 || charT[i-1]==charT[j-1]) 33 { 34 ++i; 35 ++j; 36 if(charT[i-1]!=charT[j-1]) { 37 nextval[i]=j; 38 }else { 39 nextval[i]=nextval[j]; 40 } 41 }else 42 { 43 j=nextval[j]; 44 } 45 } 46 System.out.print("next函數修正值爲:"); 47 for (i=1;i< charT.length+1; i++) { 48 System.out.print(nextval[i]+" "); 49 } 50 System.out.print("\n"); 51 } 52 public static void getNext(char[] charT,int next[]) { 53 int i=1; 54 int j=0; 55 next[0]=-1; 56 next[1]=0; 57 while(i<charT.length) 58 { 59 if(j==0 || charT[i-1]==charT[j-1]) 60 { 61 ++i; 62 ++j; 63 next[i]=j; 64 }else 65 { 66 j=next[j]; 67 } 68 } 69 System.out.print("next函數值爲:"); 70 for (i=1;i< charT.length+1; i++) { 71 System.out.print(next[i]+" "); 72 } 73 System.out.print("\n"); 74 } 75 public static void run(char[] charS,char[] charT,int pos,int nextval[]) { 76 int i=pos; 77 int j=1; 78 while(i<=charS.length && j<=charT.length) 79 { 80 if(j==0 || charS[i-1] == charT[j-1]) 81 { 82 ++i; 83 ++j; 84 }else 85 { 86 j=nextval[j]; 87 } 88 } 89 if(j>charT.length) 90 { 91 System.out.println("匹配成功,序號爲"+(i-charT.length)); 92 }else 93 { 94 System.out.println("匹配失敗"); 95 } 96 System.out.println("——程序運行完畢,檢測新的模式請從新運行程序——"); 97 } 98 }
KMP算法僅當模式與主串之間存在許多「部分匹配」的狀況下,才顯得逼BF算法快得多,可是對處理外設輸入的龐大文件頗有效,能夠邊讀入邊匹配,無需回頭重讀。指針