串的模式匹配算法——KMP算法

比BF算法改進的地方在:每一趟匹配出現字符不等時,不需回溯指針i,而是利用已經獲得的「部分匹配」的結果,將模式T向右滑儘量遠後,繼續進行比較。java

須要計算next函數值:算法

  1. next[0]=-1, next[1]=0。
  2. 在求解next[j]時,令k=next[j-1],
  3. 比較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算法快得多,可是對處理外設輸入的龐大文件頗有效,能夠邊讀入邊匹配,無需回頭重讀。指針

相關文章
相關標籤/搜索