/*
* DA-Main-KMP.cpp
*
* 两种版本, 每个版本的 找一个子串 及 找所有子串
*
* 教材版 : 《数据结构域算法》 高等教育出版社 张铭等著 2008版
* 算法导论版 :《算法导论》第二版 及 《数据结构域算法》2004版
*
* Created on: 2011-11-14
*/
#include <iostream>
#include <cstring>
using namespace std;
char Pattern[200], Str[200];
int next[200];
////////////////////////////////////////////
//教材版
////////////////////////////////////////////
void preKMP(char *P){ //优化
int j, k;
int len = strlen(P);
next[0] = -1;
j = 0, k = -1;
while(j < len - 1){
while(k >= 0 && P[j] != P[k]){
k = next[k];
}
k++, j++;
//不注的话是优化版
// if(P[j] != P[k])
next[j] = k;
// else
// next[j] = next[k];
}
}
int KMP_1(char *T, char *P, int start){
int i, j;
int tLen = strlen(T);
int pLen = strlen(P);
i = start, j = 0;
while(i < tLen && j < pLen){
while(j >= 0 && T[i] != P[j]){
j = next[j];
}
i++, j++;
}
if(j >= pLen)
return i - pLen;
return -1;
}
int KMP_2(char *T, char *P, int start){
int i, j;
int tLen = strlen(T);
int pLen = strlen(P);
i = start, j = 0;
while(i < tLen && j < pLen){
if(j == -1 || T[i] == P[j])
i++, j++;
else
j = next[j];
}
if(j >= pLen)
return i - pLen;
return -1;
}
//找所有子串
void KMP_3(char *T, char *P, int start){
int i, j;
int tLen = strlen(T);
int pLen = strlen(P);
i = start, j = 0;
while(i < tLen){
while(j >= 0 && T[i] != P[j]){
j = next[j];
}
if(j == pLen - 1){
cout << i - j << endl;
j = next[j];
}
else //注意加else!!!!!!!!!!!!!!!!!!!!!!!!!!!
i++, j++;
}
}
void KMP_4(char *T, char *P, int start){
int i, j;
int tLen = strlen(T);
int pLen = strlen(P);
i = start, j = 0;
while(i < tLen){
if(j == -1 || T[i] == P[j]){
if(j == pLen - 1){
cout << i - j << endl;
j = next[j];
}
else
i++, j++;
}
else
j = next[j];
}
}
////////////////////////////////////////
//算法导论版\04教材版 (注意 算法导论 中下标从1开始, 所以有所不同)
////////////////////////////////////////
void preKMP_CLRS(char *P){
int j, k;
int pLen = strlen(P);
next[0] = 0;
for(j=1; j<pLen; j++){
k = next[j-1];
while(k > 0 && P[j] != P[k])
k = next[k-1]; //下标从0开始,所以长度 = 下标 +1
if(P[j] == P[k])
k++;
next[j] = k;
}
}
int KMP_CLRS(char *T, char *P, int start){
int i, j;
int tLen = strlen(T);
int pLen = strlen(P);
j = 0;
for(i=start; i<tLen; i++){
while(j > 0 && T[i] != P[j]){
j = next[j-1];
}
if(T[i] == P[j])
j++;
if(j == pLen)
return i - j + 1;
}
return -1;
}
//找所有子串
void KMP_CLRS_2(char *T, char *P, int start){
int i, j;
int tLen = strlen(T);
int pLen = strlen(P);
j = 0;
for(i=start; i<tLen; i++){
while(j > 0 && T[i] != P[j]){
j = next[j-1];
}
if(T[i] == P[j]){
if(j == pLen - 1){
cout << i - j << endl;
j = next[j];
j--; //注意:长度 = 下标 + 1
}
j++;
}
}
}
void test(){
cin >> Str >> Pattern;
preKMP(Pattern);
cout << "next : " << endl;
for(int i=0; i<strlen(Pattern); i++)
cout << next[i] << "";
cout << endl << endl;
cout << KMP_1(Str, Pattern, 0) << endl;
cout << KMP_2(Str, Pattern, 0) << endl;
cout << endl;
KMP_3(Str, Pattern, 0);
cout << endl;
KMP_4(Str, Pattern, 0);
cout << endl;
/////////////////////////////////
preKMP_CLRS(Pattern);
cout << "next_CLRS : " << endl;
for(int i=0; i<strlen(Pattern); i++)
cout << next[i] << "";
cout << endl << endl;
cout << KMP_CLRS(Str, Pattern, 0) << endl;
cout << endl;
KMP_CLRS_2(Str, Pattern, 0);
}
int main(){
test();
return 0;
}