寻找密钥(字符串find,kmp)

在这里插入图片描述
第一种 string的find()函数

#include<bits/stdc++.h>
using namespace std;

int main(){
	ios::sync_with_stdio(false);
	string s1, s2;
    string::size_type position;
     //find 函数 返回s2 在s1 中的下标位置
    while(cin >> s1 >> s2){
    	position = s1.find(s2);
    	if (position != s1.npos)  //如果没找到,返回一个特别的标志c++中用npos表示,我这里npos取值是4294967295,
    	{
    	    printf("%d\n",position+1);//下标从0开始
    	}
    	else
    	{
    	    printf("-1\n");
    	}
	}
    
	return 0;
}

第二种kmp算法

#include <iostream>
#include <cstring>
using namespace std;
char text[1000005];
char str[1000005];
int nums[1000005];
int n,m;
//求出匹配字符串的前缀表 str
//next数组
void prefix_table(){
    nums[0] = 0;
    // i当前最后一个字符
    int i = 1;
    int len = 0;
    while(i < m){
        //如果最后一个字符和最长公共前后缀的后一个字符相同
        if(str[i] == str[len]){
            len ++;
            nums[i] = len;
            i ++;
        }else{
            if(len > 0)
                len = nums[len - 1];
            else {
                nums[i] = len;
                i ++;
            }
        }
    }
}
void move_prefix_table(){
    for(int i = m - 1 ; i > 0 ; i --){
        nums[i] = nums[i - 1];
    }
    nums[0] = -1;
}
// KMP搜索算法
void kmp_search(){
    prefix_table();
    move_prefix_table();

    int i,j;
    i = j = 0;

    while (i < n){
        if(j == m - 1 && text[i] == str[j]){
            printf("%d\n", i - j + 1);
            //如果是要继续匹配下去的
            j = nums[j];
//            break;
            //如果不要继续匹配直接break
        }
        //匹配成功
        if(j == - 1 || text[i] == str[j]){
            i ++;
            j ++;
        }else{
            j = nums[j];
        }
    }
}
int main()
{
    while(scanf("%s %s",text,str) != EOF){
        n = strlen(text);
        m = strlen(str);
        kmp_search();
    }
    return 0;
}

改良后的kmp

#include<iostream>
#include<stdio.h>
#include<algorithm>
#include<queue>
#include<math.h>
#include<string.h>
#include<sstream>
using namespace std;
int num[10005];
int n, m;
string str1,str2;
void prefix_table(){
	num[0] = -1;
	int i = 0, j = -1;
	while(i < n){
		if(j == -1 || str1[i] == str1[j]){
			i ++;
			j ++;
			num[i] = j;
		} else {
			j = num[j];
		}
	}
}
int kmp_search(){
	int cnt = 0;
	int i = 0, j = 0;
	while(j < m){
		if(i == -1 || str1[i] == str2[j]){
			i ++;
			j ++;
		} else {
			i = num[i];
		}
		if(i == n){
			cnt ++;
		}
	}
	return cnt;
}
int main() {
	ios::sync_with_stdio(false);
	int t;
	cin >> t;
	while(t --){
		memset(num,0,sizeof(num));
		cin >> str1 >> str2;
		n = str1.size();
		m = str2.size();
		prefix_table();
		cout << kmp_search() << endl;
	}
    return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值