一、问题描述:
对于两个字符串S、T,找到T在S中第一次出现的起始位置,若T未在S中出现,则返回-1。
二、输入描述:
两个字符串S、T。
三、输出描述:
字符串T在S中第一次出现的起始位置,若未出现,则返回-1。
四、输入例子:
ababaababcb
ababc
五、输出例子:
5
六、KMP算法解析:
KMP算法分为两步,第一步是计算next数组,第二步是根据next数组通过较节省的方式回溯来比较两个字符串。
网络上不同文章关于next数组的角标含义略有差别,这里取参考文献中王红梅《数据结构(C++版)》的next定义。
设长字符串为S,短字符串为T,next数组的长度与短字符串T的长度一致,next[j]代表使T[0]~T[k-1]=T[j-k]~T[j-1]成立的最大k值。
当T="ababc"时,next=[-1,0,0,1,2]。
通俗的讲,next[j]代表了从0往后查k个字母与从j-1往前查k个字母,这k个字母按角标排列,正好完全一样的最大k值,其作用是减少回溯的距离,从而减少比较次数。
根据《数据结构(C++版)》KMP算法的伪代码可以用如下伪代码表述:
1. 在串S和串T中分别设置比较的起始下标i和j; 2. 重复下述操作,直到S或T的所有字符均比较完毕; 2.1 如果S[i]等于T[j],继续比较S和T的下一对字符; 2.2 否则将下标j回溯到next[j]的位置,即j = next[j]; 2.3 如果j等于-1,则将下标i和j分别加1,准备下一趟比较; 3. 如果T中所有字符均比较完毕,则返回匹配的i-j; 否则返回-1;
KMP算法的C++代码如下:
1 int KMP(string S, string T) 2 { 3 vector<int> next = getNext(T); 4 int i = 0, j = 0; 5 while (S[i] != '