/*
ababababababb abababb
*/
public class Main {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
String source = sc.next();
String pattern = sc.next();
sc.close();
plain(source, pattern);
KMP(source, pattern);
}
//朴素模式,一位一位的比较,丢弃了之前失败的信息
private static void plain(String source, String pattern) {
int res=0;
int sourceLen=source.length();
int patternLen=pattern.length();
for(int i=0;i<=(sourceLen-patternLen);i++){
res++;
String str=source.substring(i, i+patternLen);
if(str.equals(pattern)){
System.out.println("朴素模式:匹配成功");
break;
}
}
System.out.println("朴素模式:一共匹配"+res+"次");
}
//KMP算法实现
private static void KMP(String source, String pattern) {
int[] next = makeNext(pattern);
int res=0;
int sourceLen=source.length();
int patternLen=pattern.length();
int i = 0;
while(i <= sourceLen-patternLen) {
res++;
String str=source.substring(i, i+patternLen);//要比较的字符串
System.out.println(str);
int count=getNext(pattern, str, next);
System.out.println("移动"+count+"步");
if(count==0){
System.out.println("KMP:匹配成功");
break;
}
i=i+count;
}
System.out.println("KMP:一共匹配"+res+"次数");
}
//得到下一次要移动的次数
private static int getNext(String pattern,String str,int[] next) {
int n = pattern.length();
char v1[] = str.toCharArray();
char v2[] = pattern.toCharArray();
for(int x = 0; n != 0; x++,n--) {
if (v1[x] != v2[x]){
if(x==0){
return 1;//如果第一个不相同,移动1步
}
return x-next[x-1];//x:第一次出现不同的索引的位置,即j
}
}
return 0;
}
//得到next数组。next[i]即前i个字符前缀和后缀共有元素最长长度
private static int[] makeNext(String pattern){
char[] P = pattern.toCharArray();
int next[] = new int[P.length];
next[0] = 0;
for (int q = 1,k = 0; q < P.length; ++q){
while(k > 0 && P[q] != P[k]) {
k = next[k-1];
}
if (P[q] == P[k]){
k++;
}
next[q] = k;
}
for(int a : next) {
System.out.print(a+" ");
}System.out.println();
return next;
}
}