//:kmp
//kmp演算法是效率最高的模式比對演算法
//其主要思想是:(假設i,j分別指向主串mStr和模式sStr的當前試匹配位置)當mStr[i]!=mStr[j]時並不
//按傳統的回溯i,j ,而是i不變j重一個算好的數組回溯,該數組可使得模式串向右
//移動儘可能多的距離。
//主要原理:假設當i,j失配的時候應該用模式的k字元與主串的j字元進行比較
//則: sStr[1~k-1] = mStr[i-k+1 ~ i-1]
//又已知:sStr[j-k+1 ~ j-1]=mStr[i-k+1 ~ i-1]
//所以: sStr[1~k-1] = sStr[j-k+1 ~ j-1];
//所以可以根據字串計算出每個字元對應的最大k,儲存在next[]中,簡便方法為:
//1,初始化 next[0] = -1 ,i,j分別代表sStr[0~i-1] = sStr[j-i-1,j-1]情況下的i,j且j+1是當前失配位置
//2,如果sStr[i] == sStr[j] ; 則sStr[0~i] = sStr[j-i-1,j],如果此時sStr[0~i+1] = sStr[j-i-1,j+1]
//則當j+1位置失配時,推到i+1位置也會失配,所以應使next[j+1] = next[i+1]如果sStr[0~i+1] != sStr[j-i-1,j+1]
//則next[j+1]=i+1;
//3,如果j<strlen(sStr)重複2
//4,退出
#include<iostream>
#include<cstdio>
int * getIndex(const char *pstr,int *next)//及時一個串的模式比對數組
{
next[0]=-1,next[1]=0;
int i = 0,j=1;
while(j < strlen(pstr))
{
if(i == -1 || pstr[i]==pstr[j])
{
//如果i==-1則將模式的第一個字元和主串的下一個字元比較
//如果pstr[i]==pstr[j]比較後續字元
++i,++j;
if(pstr[i] == pstr[j])
{//sStr[0~i] = sStr[j-i-1,j]
next[j] = next[i];
}
else
{//sStr[0~i] != sStr[j-i-1,j]
next[j]=i;
}
}
else
{
i = next[i];
}
}
return next;
}
int kmp(const char * mainSour,const char * subStr,int pos)
{
int res = -1;
int * next = new int[strlen(subStr)];
//計算數組
getIndex(subStr,next);
int i=pos,j=0,end= strlen(subStr);
while(i<end)//未到達主串的尾部
{
if(mainSour[i] == subStr[j] || j == -1)
{
++i,++j;
if(!subStr[j])
{
res = i-strlen(subStr);
break;
}
}
else
{//失配則回溯j
j = next[j];
}
}
return res;
}
int main()
{
std::cout<<kmp("ababcabcacbab","abcac",0)<<std::endl;
return 0;
}