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

比BF算法改进的地方在:每一趟匹配出现字符不等时,不需回溯指针i,而是利用已经得到的“部分匹配”的结果,将模式T向右滑尽可能远后,继续进行比较。

需要计算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。

 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算法快得多,但是对处理外设输入的庞大文件很有效,可以边读入边匹配,无需回头重读。

猜你喜欢

转载自www.cnblogs.com/kt-xb/p/11107115.html