遊戲領域區塊鏈探索
阿新 • • 發佈:2022-05-03
package demo2;
public class P83 {
//KMP演算法
//思路:減少回退。
//主串s,模式串p;指標i、j分別指向s、p來比較。
//假設有兩個模式串,p1在j失配,說明前面0~(j-1)與s相同,這段中p1的字尾與p2的字首重合部分免檢(這部分p2等於p1等於s)。
//易得,公共前後綴與s無關,可以由p本身得到。算出跳轉位置構成next陣列,j=next[j],後一個j為失配位置
public static void main(String[] args) {
String s="babaabbabc";
String p="babc";
System.out.println(kmp(s, p));
}
static int[] next(String p) { int pLen=p.length(); int[] next=new int[pLen]; char[] pArr=p.toCharArray(); next[0]=-1; //-1是為了處理這一要i++的特殊情況 if(pLen==1) return next; next[1]=0; int j=1; //遞推法,求之後的next[] //原理:next[j]等於k,就是j處失配後有k長度的公共前後綴。 int k=next[j]; while(j<pLen-1) { //若j、k的字元相同,則(j+1)處失配的公共前後綴為k+1 if(k<0 || pArr[j]==pArr[k]) { next[++j]=++k; } //若不同,則next[j]的值k不可用,繼續找相同字元 else { k=next[k]; } } return next; } static int kmp(String s,String p) { int[] next=next(p); int i=0; int j=0; int sLen=s.length(); int pLen=p.length(); while(i<sLen) { if(j==-1 || s.charAt(i)==p.charAt(j)) { i++; j++; } else { j=next[j]; } if(j==pLen) { //匹配成功,此時i、j在結尾的再後一位 return i-pLen; } } return -1; //找不到 }
}