字符串问题:BF与KMP算法

BF算法
BF算法模板

时间复杂度:
最好的情况O(i+j)
最糟糕的情况O(i*m)

步骤:
1、分别用计数指针i和j指示主串s和子串t,i=0,j=0
2、匹配未到串尾,执行如下循环
(1)s[ i ]==t[ j ],执行i++,j++,继续匹配后续字符
(2)s[ i ]!=t[ j ],回溯一步,i=i-j+1;j=0
3、若子串t[ j ] = =’\0’ ,匹配成功
4、否则匹配失败

#include <bits/stdc++.h>
using namespace std;
string s,t;
int pos;
void Index_BF(string s,string t)
{
    int i=0,j=0;
    while(i<s.length()&&j<t.length())
    {
        if(s[ i ] = =t[ j ])
        {
            i++;j++;
        }
        else
        {
             i=i-j+1;j=0;
        }
    }
    if(t[ j ] =='\0')
    {
        pos=i-t.length()+1;
        printf("match success,in father's string n'th:%d\n",pos);
    }
    else
        printf("Match fail \n");
}
int main()
{
    while(cin>>s&&s[ 0 ]!='#')
    {
         cin>>t;
         Index_BF(s,t);
     }
     return 0;
 }

在这里插入图片描述
BF基础算法用于匹配字符串
统计子串在主串中的出现次数:

KMP算法
题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=2087
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <string>
using namespace std;
string s,t;
int a[100000000];

void get_next(string t,int a[])  //子串t的next函数值并存入串next
{
    int i=0,j=-1;
    a[0]=-1;
    while(i<t.length())
    {
        if(j==-1||t[i] == t[j])
        {
            ++i;
            ++j;
            if(t[i]==t[j])
                a[i]=a[j];
            else
                a[i]=j;
        }
        else
            j=a[j];
    }
}

void get_kmp(string s,string t)  //主串s,子串t
{
    int cnt=0;      //记录剪出个数
    int i=0,j=0;      //i记录主串,j记录子串
    while(i<s.length())  //子串与主串均没有比较到串尾
    {
        if(j==-1||s[i]==t[j])    //比较后续字符串
        {
            ++i;
            ++j;
        }
        else
            j=a[j];   //模式串向右移动

        if(j==t.length())  //匹配成功一次,主串还没有到串尾
        {
            ++cnt;  ///主串s中判断过的位置不需要再次进行判断,所以直接让j=0即可

            j=0;  //子串计数器为初始状态
        }
    }
    printf("%d\n",cnt);  //输出
}

int main()
{
    while(cin>>s&&s[0]!='#')
    {
        cin>>t;
        get_next(t,a);
        get_kmp(s,t);
    }
    return 0;
}

KMP算法模板
时间复杂度: O(i * j),实际的执行时间O(i + j) 特点:指示主串的指针不需要回溯,整个匹配过程对主串进行扫描
#include <bits/stdc++.h>
using namespace std;
string s,t;
int a[10000000];

void get_next(string t,int a[])
{
    int i=0,j=-1;
    a[0]=-1;
    while(i<(t.length()))
    {
        if(j==-1||t[i]==t[j])
        {
            ++i;++j;
            if(t[i]!=t[j])
                a[i]=j;
            else
                a[i]=a[j];
        }
        else
            j=a[j];
    }
}

 void get_KMP(string s,string t)
 {
     int cnt=0;
    int i=0,j=0;
    while(i<s.length())
    {
        if(j==-1||s[i]==t[j])
        {
            ++i;
            ++j;
        }
        else
            j=a[j];

        if(j==t.length())
        {
            ++cnt;
            j=0;
        }
    }
    printf("%d\n",cnt);
}

int main()
{
    while(cin>>s&&s[0]!='@')
    {
        cin>>t;
        get_next(t,a);
        get_KMP(s,t);
    }
    return 0;
}

在这里插入图片描述
看了这篇博客更好的理解KMP,利用子串后移动
www.ruanyifeng.com/blog/2013/05/Knuth–Morris–Pratt_algorithm.html

猜你喜欢

转载自blog.csdn.net/weixin_43517282/article/details/89637055