题目:http://ybt.ssoier.cn:8088/problem_show.php?pid=1465
题目思路:KMP模板题,该说的都在代码里
#include<bits/stdc++.h>
using namespace std;
int nexT[1001],t0,p0;
string t,p;
int KMP(string n,int n0,string m,int m0){
int i=0,j=0,k=0;
while(i<n0){
if(j==-1||n[i]==m[j]){
//如果是在字符串开始或者主子串字符对上了
++i;
++j;
//i,j一起走
if(j==m0){//如果全对完了
i=i+m0-1;
//更新以下i
k++;
//子串数+1
}
}
else{
//否则
j=nexT[j];
//二营长,你他娘的next数组呢
}
}
return k;
//返回字符数量
}
void hnext(string o,int o0){//寻找next数组
int j=0,k=-1;
nexT[j]=k;//先把next[0]变成-1
//如果第一个对上的数字就不对
//那么只动j是不可能找到成功的串的
//所以把他变成-1就是做一个信号
//让程序知道“我需要动i”这件事
while(j<o0){//数组不超限制是肯定的
if(k==-1||o[j]==o[k]){
nexT[++j]=++k;
//如果k是-1
//那么就证明前面连个屁的对应都没有
//甚至可能连字符都没有
//再往前倒腾也不太现实
//那就只能向后来一位
//即next[j+1]=k+1
//那如果我们现在看到的两个字符相同
//比如:
//A C D A C D C
// k j j+1
//那么前面是一一对应的
//就是k和k前面的东西
//和k+1~j的地方已经对过了
//能和k+1~j对上的主串部分
//就一定能和0~k的部分对上
//所以如果在j+1的地方出了岔子
//那就可以直接把0~k忽略
//直接k+1一步到位
//所以此时next[j+1]=k+1
}
else{
//如果不相等了
//比如:
//A B A C D A B A B C
// k j j+1
//每一个循环的宗旨都是求出next[j+1]
//所以j的位置不能动,但是还对不上
//所以就要单独动k
//也就是调整移动的长度
//这就需要我们调整开始的位置
//匹配长度会不可避免的变小
//但无论k怎么变
//它都会在我们已经对应好的串里
//通俗地说
//是在用前缀的前缀匹配后缀的后缀
//而在那个已经匹配出来的串子里
//是有一个更短也能100%对的缀的
//它的串尾的下标就是next[k]
//那直接让他滚过去不就得了
k=nexT[k];
}
}
}
int main(){
while(1){
cin>>t;//输入主串
if(t=="#"){//结束了
break;//再见
}
cin>>p;//输入子串
t0=t.size();
p0=p.size();
hnext(p,p0);//把对应的next找出来
printf("%d\n",KMP(t,t0,p,p0));
//算完输出
}
return 0;
}
![]()

浙公网安备 33010602011771号