#include <iostream>
#include <string>
#define N 50
using namespace std;
/*主要思路是n[pos]=k+1等价于:*/
/*1. 0<=k<=j-1*/
/*2. ptr[0]-ptr[k-1]每一位均与ptr[pos-k]-ptr[pos-1]相同*/
/*3. ptr[k]=ptr[pos]*/
/*只要对满足1.、2.的k验证是否满足3.即可*/
/*得到特征向量的函数,采用了递归的思想*/
int GetN(char *ptr, int *n, int pos) {
if (pos == 0) { //第一位必为零,递归出口
n[0] = 0;
return 0;
}
else {
int k = GetN(ptr, n, pos - 1); //k即为特征向量的值,即如此得到的k一定满足条件1.、2.
cmp:
if (ptr[pos] == ptr[k]) { //满足条件3.
n[pos] = k + 1; //等于k+1刚好是对应相同字符的个数
return k + 1;
}
else if (k > 0) { //从大到小,找满足1.、2.条件的前一个k值是否满足条件3.
k = n[k - 1];
goto cmp;
}
else { //直到k=0也没找到则n[pos]=0
n[pos] = 0;
return 0;
}
}
}
int main() {
string str, ptr; //str为源字符串,ptr为目标字符串
unsigned int i, j; //这里用unsigned是因为后来的'j<ptr.size()'会有warning......
getline(cin, str);
getline(cin, ptr);
int n[N]; //n为存放ptr各位置特征向量的数组
GetN(&ptr[0], n, ptr.size() - 1);
for (i = 0, j = 0; j < ptr.size();) {
if (str.size() - i < ptr.size() - j) { //若str[i]之后的字符个数少于ptr[j]之后的字符个数,则没有相同字符串
cout << "not found" << endl;
return 0;
}
else {
if (ptr[j] != str[i]&&j != 0) { //将ptr首位移到str[i-n[j-1]]的位置
j = n[j - 1];
}
else if (ptr[j] != str[i] && j == 0) {
i++;
}
else if (ptr[j] == str[i])
{
i++;
j++;
}
}
}
cout << i - j; //最终i-j的值即为所求位置
return 0;
}
主要思路已经写在代码里了,个人感觉比较好的就是采用递归得到的k值一定满足条件1和条件2,只要对条件3进行判定就好了。
测试结果:
/*返回的是出现相同字符串的位置*/
/*如果各位发现了什么bug或者有什么建议请一定在评论区指出*/