题目描述
PIPI又来考察大家字符串处理的能力了。
给定一个字符串S,以及字符串T,你需要回答:
(1)T是否是S的子串。如果是输出YES,并回答问题(2);如果不是,输出NO。
(2)T作为S的子串在S中出现了几次?
请你来解决这个简单的问题。
注意:子串不是子序列。子串要求连续,如”abc"为"aabcc“的子串。
输入
第一行给出字符串S。|S|<=1e6.
第二行给出字符串T。|T|<=1e6.
输出
首先回答问题(1),若T为S子串,输出YES,第二行回答问题(2).若不是,直接输出NO。
样例输入
abcabcabc
bc
样例输出
YES
3
///kmp算法
#include <bits/stdc++.h>
using namespace std;
const int N=1e6+5;
char s1[N],s2[N];
int Next[N];
int n,m;
void getNext()
{
int j=0,k=-1;
Next[0]=-1;
while(j<m-1) ///总共需要求到m-1位,可以通过m-2位的值求出m-1位
{
if(k==-1||s2[j]==s2[k])
Next[++j]=++k; ///++的顺序不能错
else
k=Next[k];
}
}
int kmp()
{
getNext();
int i=0,j=0,ans=0;
while(i<n)
{
if(j==-1||s1[i]==s2[j])
{
if(j+1==m) ///当j+1等于m时 已匹配到相等的字符串
{
ans++;
j=Next[j]; ///回溯,当做不匹配继续处理并记录个数
}
else
{
i++;
j++;
}
}
else
j=Next[j];
}
return ans;
}
int main()
{
scanf("%s %s",s1,s2);
n=strlen(s1);m=strlen(s2);
int ans=kmp();
if(ans==0) printf("NO\n");
else printf("YES\n%d\n",ans);
}