Description
给定两个字符串string1和string2,判断string2是否为string1的子串。
Input
输入包含多组数据,每组测试数据包含两行,第一行代表string1(长度小于1000000),第二行代表string2(长度小于1000000),string1和string2中保证不出现空格。
Output
对于每组输入数据,若string2是string1的子串,则输出string2在string1中的位置,若不是,输出-1。
Sample
Input
abc a 123456 45 abc ddd
Output
1 4 -1
#include <iostream>
#include <string>
using namespace std;
const int N = 1e6 + 5;
int Next[N];
void getnext(string p, int next[])
{
int l = p.size();
Next[0] = -1;//表示在第i个位置的字符前的最长前缀和后缀和
int k = -1;
int j = 0;
while(j < l - 1)
{
if(k == -1 || p[k] == p[j])//p[j]表示前缀,p[j]表示后缀
{
j++;
k++;
if(p[j] != p[k])
Next[j] = k;
else
Next[j] = Next[k];
}
else
k = Next[k];
}
}
int Kmpsearch(string s, string p)
{
int i = 0, j = 0;
int sl = s.size(), pl = p.size();
while(i < sl && j < pl)
{
if(j == -1|| s[i] == p[j])//这里j = -1的作用是为了让第一个字符不匹配的时候继续比较
{
i++;
j++;
}
else
j = Next[j];//匹配失败,向右移动j - Next[j],因为Next[j]表示的是在p[j]之前的最长前缀和后缀和,即p[j]前存在相同的序列。如abcabd,在d匹配失败,则向右移动两个单位
}
if(j == pl)
return i - j + 1;//j的值表示前面已经匹配的字符数
else
return -1;
}
int main()
{
string a, b;
while(cin >> a >> b)
{
getnext(b, Next);
cout << Kmpsearch(a, b) << endl;
}
return 0;
}