88888888y

导航

 

题目: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;
}
 

 


 





posted on 2022-05-14 11:26  88888888y  阅读(147)  评论(2)    收藏  举报