BF KMP

查找子串

BF

BF算法 也就是在一个字符串中 查找某一字串的位置

#include<iostream>
using namespace std;
int main()
{
	string a;
	string b;
	cin >> a >> b;
	int lena = a.size();
	int lenb = b.size();
	int i=0, j=0;
	while(i<lena&&j<lenb) //a[i]!='\0'&&b[j]!='\0';
	{
		if (a[i] == b[j])
		{
			i++;
			j++;
		}
		else
		{
			i = i - j + 2;
			j = 0;
		}
	}
	if (j >= lenb) //a[j]=='\0'
		cout <<"匹配的子串位置是"<< i - lenb << endl;
	else
		cout<<"没有找到"<<endl;
}

-注意这里i=i-j+2 是当i从0开始没匹配到字串时 需要回溯到i=1的位置 再不符合还需要回溯到i=2的位置 这里可以当一个公式记忆 匹配的模式串(子串)则需要回到开头 若不想用这个回溯公式 可以用一个变量标记

#include<iostream>
using namespace std;
int main()
{
	string a;
	string b;
	cin >> a >> b;
	int lena = a.size();
	int lenb = b.size();
	int i=0, j=0,flag=0;
	while(i<lena&&j<lenb) //a[i]!='\0'&&b[j]!='\0';
	{
		if (a[i] == b[j])
		{
			i++;
			j++;
		}
		else
		{
			flag++;;
			i = flag;
			j = 0;
		}
	}
	if (j >= lenb) //a[j]=='\0'
		cout <<"匹配的子串位置是"<< flag << endl;
	else
		cout<<"没有找到"<<endl;
}

KMP

#include <iostream>
#include <string>
#include <vector>

using namespace std;

// 计算next表
inline void makeNextTable(const string&W, vector<int>&next)
{
    // pos是当前在模式串的位置,cnd是匹配串的位置
    // 由于无论什么模式串,前两位都固定为-1和0,所以pos直接从2开始
    int pos = 2;
    int cnd = 0;
    next[0] = -1;
    next[1] = 0;
    while (pos < W.size())
    {
        // 第一种情况:子串匹配成功,向前继续
        if (W[pos - 1] == W[cnd]) // 由于要找的是pos前面的字符串的最长相同前缀后缀,所以-1
        {
            next[pos] = cnd + 1;
            cnd++;
            pos++;
        }
        // 第二种情况,子串匹配失败,但可以匹配到更小串,比如“aabaaa”中W[6]=2而不是1
        else if (cnd > 0)
        {
            cnd = next[cnd];
        }
        // 第三种情况,子串匹配失败,且什么都匹配不了
        else
        {
            next[pos] = 0;
            pos++;
        }
    }
}

// 输出匹配成功的位置(首字母),返回值是匹配成功的次数
int countKMP(const string&S, const string&W)
{
    vector<int> next(W.size());

    makeNextTable(W, next);

    // print next表
    cout << "next表:" << endl;
    for (int i = 0; i < W.size(); ++i) {
        if (i == W.size() - 1) {
            cout << next[i] << endl;
        }
        else {
            cout << next[i] << " ";
        }
    }

    int m = 0; // S串中匹配的第一个位置
    int i = 0; // 模式串中已经匹配到的位置
    int count = 0; // 匹配成功的次数
    while (m+i < S.size())
    {
        if (W[i] == S[m + i]) { // 匹配成功
            if (i == W.size() - 1) // 一次匹配完毕
            {
                count++;
                cout << "The " << count << "th match at " << m << endl;
                m = m + i - next[i];
                i = next[i];
            }
            else // 匹配了部分,继续匹配
            {
                i++;
            }
        }
        else // 匹配失败
        {
            if (next[i] > -1) // 虽然当前匹配失败,但是可以匹配到更小串
            {
                m = m + i - next[i];
                i = next[i];
            }
            else // 完全不匹配,即从第一个字母起就不匹配了
            {
                m++;
                i = 0;
            }
        }
    }

    return count;
}

int main()
{
    string S;// 原串
    string W;// 模式串 
    cout << "input the origin string" << endl;
    cin >> S;
    cout << "intput the search string" << endl;
    cin >> W;
    int count = countKMP(S, W);
    cout << "The times match successfully: " << count << endl;
    system("PAUSE");
    return 0;
}

kmp算法较难理解,很多博客对其有详细的介绍,这里引用了一位博主的源码,具体不做详细介绍,感兴趣的可以看一下其他博主对kmp算法的详细讲解。

库函数

#include<iostream>
using namespace std;
int main()
{
	string a;
	string b;
	cin >> a >> b;
	int ret=a.find(b);
	cout <<"匹配位置是:"<< ret << endl;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值