Description
给定一个源串s和n个子串stri。判断stri是否是s的子串。
Input
输入数据有多组,对于每组测试数据 第一行源串S(S长度小于100000),第二行一个整数n, 表示下面有n个查询,每行一个字符串str。
Output
若str是S的子串,输出 yes 否则输出 no
Sample Input
acmicpczjnuduzongfei
3
icpc
du
liu
Sample Output
yes
yes
no
代码区:
#include <iostream>
#include <cstdio>
#include <string.h>
#include <cmath>
using namespace std;
int nextt[100005];//这个地方挺坑的,不能直接叫next,之前叫next了可以运行但就是oj通不过,枯了
void GetNextt(string s)//获取kmp算法的next值(注意本函数中的比较都是在自己子串中进行比较的,和主字符串没有关系)
{
int i=0,j=-1;
int length=s.size();//s.size()为s字符串的长度
nextt[0]=-1;//先将第一个next定为-1
while(i<length)//依次对字符串每个字母遍历
{
if(j==-1||s[i]==s[j])//只有当j还是-1(也就是前面比较失败了,从头开始)或者成功发现字符串中有相同的子串时
{
i++;j++;//第一个子串的开头和第二个相同子串(起码目前是)都往后一位
nextt[i]=j;//标记next数组,表示i开始的子串和j开始的子串有相同的元素
}
else
j=nextt[j];//出现不相等的字母比较失败,j指针回到next标记的位置重新开始匹配
}
}
int kmp(string s,string t)//kmp算法主体
{
int i=0,j=0;
GetNextt(t);//调用函数,生成next数组
int length1=s.size();//主字符串长度
int length2=t.size();//子串长度
while(i<length1)//从第一个字母依次遍历直到到了字符串末尾
{
if(j==-1||s[i]==t[j])//只有当j还是-1(也就是前面比较失败了,从头开始)或者成功发现字符串中有相同的子串时
{
i++;//主串的开头和第一个相同子串(起码目前是)都往后一位
j++;
}
else j=nextt[j];//比较失败时就将子串指针指回上一个相同的子串的位置
if(j>=length2) return i-length2;
//当最后j的值大于我们需要判断的子串长度时,有两种可能性,一是子串匹配成功了,二是子串每个字母都比较过去了还没有成功
//所以需要返回一个当前判断到的主串的位置减去子串的长度
//因为i的值只有在连续匹配成功的情况下才会一直加到子串长度(和j一起加),当i>=j时也就匹配成功了
}
return -1;//返回-1代表子串匹配失败
}
int main()
{
string s,t;
int c;
cin >> s >> c;
while(c--)//输入子串数量
{
cin >> t;
int ans;
ans=kmp(s,t);//调用kmp函数比较
if(ans>=0) cout << "yes" << endl;//当返回值大于等于0时说明匹配成功
else cout << "no" << endl;
}
return 0;
}
新手上路,有错请指正