POJ-3461 Oulipo

POJ-3461 Oulipo

题目链接:POJ-3461
在这里插入图片描述
题目大意:寻找一个字符串在另一个字符串中一共出现了多少次

解题思路:完全的kmp算法加点料 最一开始我是在模式串里面找到匹配串的开头的那个字母然后kmp的,后来果断TLE了,然后改成在找到第一个相匹配的位置后j = next[j - 1],因为要直接用之前在模式串后面部分匹配好的串片段和匹配串前面的相同的串片段。所以省去不少时间。这题挺有助于理解kmp的 之前因为index越过了我设的数组大小导致RE了好几次

代码块

#include<iostream>
#include<string>
#include<cstring>
#include<cstdio>

using namespace std;

int next[10009];
int index = 0;

string strA, strB;

// 获取一个字串的部分匹配值
void setNext() {
	next[0] = 0;
	int i = 1, j = 0;
	// i指向后缀待比较的最后位置
	// j指向前缀待比较的最后位置
	while(i < strB.length()) {
		// 如果前缀的最后位置和后缀的最后位置相同 则肯定是从0-j位置的串都相同
		if(strB[i] == strB[j]) {
			// 所以当前位置所生成的后缀与前缀的最长公共长度就是++j
			next[i] = ++j;
			//这个位置判断完 向下移动一位
			++i;
		} else if(j!=0) {
			// 如果这个i j位置不相同 那么就判断i是否和next[j - 1]的位置的元素是否相同 因为0-next[j - 1]这段的字符串一定和后面 j前面的的后缀字符串相同
			j = next[j - 1];
		} else {
			// 如果j等于零 i和j处的字符串还不对应 说明当前处的字符串后缀不可能与前缀相同 所以当前位置为0 向后移动一位
			next[i] = 0;
			++i;
		}
	}
}

int kmp() {
	setNext();
	int lenA = strA.length();
	int lenB = strB.length();
	// 从头进行比较
	int i = 0, j = 0, sum = 0;// i为模式串当前判断的字符位置 j为匹配串当前判断的字符位置
	// 当i或j超出范围即可出现答案
	while(i < lenA && j < lenB) {
		// 如果匹配串已经退回最后一个字符 不管是否与模式串匹配 都要i++ 如果 两个位置的字符相同的话 那么j++
		if(j == 0 || strA[i] == strB[j]) {
			if(strA[i] == strB[j]) {
				j++;
			}
			i++;
		} else {
			j = next[j - 1];
		}
		if(j == lenB) {
			sum++;
			j = next[j - 1];
		}
	}
	return sum;
}

int main() {
	int n;
	cin>>n;
	getchar();
	while(n--) {
		getline(cin, strB);
		getline(cin, strA);
		int sum = 0;
		sum = kmp();
		cout<<sum<<endl;
		memset(next,0,sizeof(next));
		index = 0;
	}
	return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值