一:暴力解法
KMP算法要解决的问题就是在字符串(也叫主串)中的模式(pattern)定位问题。说简单点就是我们平时常说的关键字搜索。模式串就是关键字(接下来称它为P),如果它在一个主串(接下来称为T)中出现,就返回它的具体位置,否则返回-1(常用手段)。
思路:两个字符串,如果字符相等,i,j往后移一位;不相等时,i往后移一位,j归0,继续这个循环直到结束
package Kmp;
public class kmpBL {
public static void main(String[] args) {
String t="abcccd";
String p="ccd";
System.out.println(kmp_index(t,p));
}
public static int kmp_index(String ts,String ps){
char[]tt=ts.toCharArray();
char[]ss=ps.toCharArray();
int i=0;
int j=0;
while(i<tt.length&&j<ss.length){
if(tt[i]==ss[j]){
i++;
j++;
}
else{
i=i-j+1;
j=0;
}
}
if(j==ss.length) return i-j;
else return -1;
}
}
二:kmp解法
相等时i,j都往后移一个,不相等时j移动到适当位置,而不是暴力那种,适当的位置就是next数组了
1.1 求next数组思路:
字符串下标从0开始,next[0]=-1
比如字符串 ababaabab
字符串 | a | ab | aba | abab | ababa | ababaa | ababaab | ababaaba | ababaabab |
next[j] | -1 | 0 | 0 | 1 | 2 | 3 | 1 | 2 | 3 |
1.2 求next数组代码:
public static int[] getNext(char[] t){
int []next=new int[t.length];
next[0]=-1;
int j=0;
int k=-1;
while(j<t.length-1){
if(k==-1||t[j]==t[k]){
next[++j]=++k;
}
else{
k=next[k];
}
}
return next;
}
2.1 对next数组改进:nextval数组
还拿上边的字符串求nextval数组:
字符串 ababaabab
字符串 | a | ab | aba | abab | ababa | ababaa | ababaab | ababaaba | ababaabab |
next[j] | -1 | 0 | 0 | 1 | 2 | 3 | 1 | 2 | 3 |
nextval[j] | -1 | 0 | -1 | 0 | -1 | 3 | 0 | -1 | 0 |
nextval数组求解方法:
第0个字符是a,next[0]=-1,nextval[0]=-1
第1个字符是b,next[1]=0,然后找0处字符,为a,ab不相等,所以nextva[1]为0
第2个字符是a,next[2]=0,然后找0处字符,为a,aa相等,到边界0了,再往前找就没了,所以nextval[2]为-1
具体方法就是:当前字符对应的next数组的值 为 当前字符往前回溯的字符下标,如果相等,继续往前回溯,直到不相等或边界为止,nextval值就是当前最后一次相等的next值或者边界值;如果第一次就不相等nextval值就是当前next值
2.2 求nextVal数组代码
public static int[] getValNext(char[] t){
int []nextVal=new int[t.length];
nextVal[0]=-1;
int j=0;
int k=-1;
while(j<t.length-1){
if(k==-1||t[j]==t[k]){
++j;
++k;
if(t[j]==t[k]) nextVal[j]=nextVal[k];
else nextVal[j]=k;
}
else{
k=nextVal[k];
}
}
return nextVal;
}
3. kmp算法代码(nextVal数组实现):
package Kmp;
import java.util.Scanner;
public class kmp1 {
public static int[] getValNext(char[] t){
int []nextVal=new int[t.length];
nextVal[0]=-1;
int j=0;
int k=-1;
while(j<t.length-1){
if(k==-1||t[j]==t[k]){
++j;
++k;
if(t[j]==t[k]) nextVal[j]=nextVal[k];
else nextVal[j]=k;
}
else{
k=nextVal[k];
}
}
return nextVal;
}
public static int kmp_Index(char[]s,char[]t){
int []next=getValNext(t);
for(int i=0;i<next.length;i++)
System.out.println(next[i]);
int i=0;
int j=0;
while(i<=s.length-1&&j<=t.length-1){
if(j==-1||s[i]==t[j]){
i++;
j++;
}
else{
j=next[j];
}
}
if(j<t.length) return -1;
else return i-t.length;
}
public static void main(String[] args) {
Scanner scan=new Scanner(System.in);
while(scan.hasNextLine()){
String s=scan.nextLine();
String t=scan.nextLine();
char[]ss=s.toCharArray();
char[]tt=t.toCharArray();
if(kmp_Index(tt,ss)==-1)
System.out.println("NO");
else
System.out.println("YES");
}
}
}