网上看了好多关于KMP算法的,但是都是看的不清不楚的,用了好多术语,不明白,后来自己根据结果倒推了过程,不知对不对,
暂时先记下来,
KMP算法,需要预先处理子串,然后建立一个int类型next数组(名字无所谓,主要是存储一些关于子串的信息),这里有几点要注意:
next数组计算方法(假定j为数字下标,j >= 1)
j = 1时, next[j] = 0, 这个是必定的,所有的next子串模式数组next[1] 都是0, next[0]这个弃之不用,
当然只是在下标的范围上不用,实际的数组空间我们还是要用的,也就是说,我们算法中的j值于实际的下标之间有
下标 = j - 1
的换算关系。
j = 2时, next[j] = 1, 这个也是定死的,但仍你按后边的公式也可以推出这个的值,
j > 2时, next[j] 的值为
j位置前紧邻的字符串与子串第一个字符开始最大的相同子串数+1。这句是我从网上copy 来的,看不懂,但是我觉着应该是这样的:
j位置前紧邻的字符与子串第一个字符开始最大的相同字符数+1,
我们举个例子说明:
比如有子串: abaabcac, 它的next模式数组应该是0,1,1,2,2,3,1,2, 我们来看下是怎样得来的,
第一位是0,第二位是1,这是定死的,所以有0,1,
我们看第三位,第三位对应的字符是a,注意我们的下标从1,开始:
abaabcac
他前边的字符是b,b对应的next值是1,所以,我们从子串的一个字符开始比较,
因为子串第一个字符是a,所以b没有相同的字符,则next[3] = 0 + 1,
我们看第四位,对应的字符是a,
abaabcac
它前边的字符是a,并且next[3] = 1, 所以我们从子串的第一位开始比较, a == a, 所有有一个字符相同,所有next[4] = 1 + 1,
我们看第五位,对应的字符是b,
abaabcac
他前边的字符是a,对应的next[4] = 2, 所以从第二位开始比较,a != b, 不同,要向前与第一位比较,a == a, 有一个字符相同,所有
next[5] = 1 + 1, 其实这里可以取得前一个字符的next值,
n = next[j - 1], 此处 n = 2, 然后在比较指针向前移动时,n 相应 - 1, 比如此处,在a != b是, 要与前一位比较
则n 要 -1,
我们看第六位,对应的字符是c,
abaabcac
他前边的字符是b,对应的next[5] = 2, 所以从第二位开始比较,b == b, 所以, next[6] = next[5] + 1,
我们看第七位,对应的字符是a,,
abaabcac
他前边的字符是c,对应的next[6] = 3, 所以从第三位开始比较,
定义 n = next[6] = 3
a != c,
所有要与第二位再次比较,同时n = n -1;
b != c,
与第一位比较,n = n -1,
a != c,
所以此位next[7] = 0 + 1
我们看第八位,对应的字符是c,
abaabcac
他前边的字符是a,对应的next[7] = 1, 所以于第一位比较 a == a,
所以 next[ 8] = 1 + 1 = 2,
所以最终的next 数字序列是: 0,1,1,2,2,3,1,2
然后我们看比较过程,这里就比较简单了:
比较方法:
1.当S[i]=P[j],则:i++,j++;
2.当S[i]!=P[j],如果此时j!=0,则j=next[j],再继续比较;
如果j=0 则i++,j++,再继续比较
void
parseNextVector(string &substr, vector<int> &nextVec
)
{
int j = 1;
nextVec.push_back(0); //pos 1; pos 0 never used.
j++;
nextVec.push_back(1); // pos 2;
j++;
for (int i = 3; i <= substr.length(); i++)
{
int j = i -1;
int x = nextVec.back();
while(1)
{
cout << substr[j - 1] << " " << substr[x - 1] <<endl;
if (substr[j -1] == substr[x - 1])
{
nextVec.push_back(x + 1);
break;
}
else
{
x--;
if (x == 0)
{
nextVec.push_back(1);
break;
}
}
}
}
}
int
kmpSearch(string& str, string& subStr, vector<int>& nextVec)
{
int j = 0;
int i = 0;
while(i < str.length())
{
cout <<str[i] << " " <<subStr[j] <<endl;
if (str[i] == subStr[j])
{
if (j == subStr.length() - 1)
{
cout << i << " " << j <<endl;
return (i - j);
}
j++;
i++;
}
else
{
j = nextVec[j];
j = j - 1;
if (j < -1)
{
cout << "error: " << j <<endl;
return -1;
}
else if (j == -1)
{
j++;
i++;
}
}
}
return -1;
}
原文章地址:
http://blog.sina.com.cn/s/blog_5f240fc40100cjgr.html
这里的比较代码很简单,我没仔细看,