#include<iostream>
#include<string>
using namespace std;
/*
* BF算法
* 基本思想:
*从主串S的第一个字符开始和模式T(子串)的第一个字符进行比较,若相等,则继续比较两者的后续字符;
*若不相等,则从主串S的第二个字符开始和模式T的第一个字符进行比较,重复上述过程,若T中的字符全部比较完毕,则说明本趟匹配成功;
*若最后一轮匹配的起始位置是n-m(n为主串的长度,m为模式T的长度),则主串S中剩下的字符不足够匹配整个模式T,匹配失败。
*这个算法称为朴素的模式匹配算法,简称BF算法。
*/
int BF(string &s, string &t)
{
int i=0,j=0,count=0; //i指向主串s,j指向子串t,count计算匹配的字符长度
while(i < s.size())
{
if(s.at(i) == t.at(j)) //如果匹配
{
i++; //指针后移
j++;
count++;
}
else { //匹配失败
i++;
j = 0;
count = 0;
}
if(count == t.size())
{
cout<<"字符串匹配成功,起始位置为:"<<i - count + 1<<endl;
return (i - count + 1);
}
}
cout<<"字符串匹配失败!"<<endl;
return 0;
}
//KMP算法中求next数组
void GetNext(string &t, int *next)
{
next[1] = 0;
int j = 1;
int k = 0;
while(j < t.size())
{
if((k == 0) || (t[j] == t[k])){
j++;
k++;
next[j] = k;
}
else k = next[k];
}
}
//KMP算法实现
/*
*伪代码:
* 1.在串S和串T中分别设比较的起始下标i和j
* 2.循环直到S中所剩字符长度小于T的长度或T中所有字符均比较完毕
* 2.1 如果S[i] = T[j],则继续比较S和T的下一个字符,否则
* 2.2 将j向右滑动到next[j]位置,即j=next[j];
* 2.3 如果j = 0,则将i和j分别加1,准备下一趟比较
* 3.如果T中的所有字符均比较完毕,则返回匹配的起始下标,否则返回0
*/
int KMP(string &s, string &t)
{
int i = 0,j = 0;
int n = t.size(); //子串的长度
int *next = new int[n];
GetNext(t, next); //求出每一个j对应的next[j]
while(i < s.size() && j < t.size())
{
if(j == 0 || (s.at(i) == t.at(j)))
{
i++;
j++;
}
else {
j = next[j];
}
if(j == t.size())
{
int index = i - t.size() + 1;
cout<<"字符串匹配成功,起始位置为:"<<index<<endl;
return index;
}
}
cout<<"字符串匹配失败!"<<endl;
return 0;
}
//BM算法中的dist函数(滑动距离函数)
int dist(string &t, char ch) //t为子串,ch为主串中的任意字符
{
int len = t.size();
int i = len - 1;
if(ch == t.at(i))
return len;
i--;
while(i >= 0)
{
if(ch == t.at(i))
{
return len - 1 - i; //返回滑动距离
}
else {
i--;
}
}
return len;
}
//BM算法
/*基本思想:有
*假设将主串中自位置i起往左的一个子串与模式进行从右到左的匹配过程中,若发现不匹配
*,则下次应从主串的i+dist(Si)位置开始重新进行新一轮的匹配,其效果相当于把模式和主串均向右
* 滑过一段距离dist(Si),即跳过dist(Si)个字符而无需进行比较。
*/
int BM(string &s, string &t, int n, int m)
{
//主串的长度为n,模式串的长度为m,主串和模式的数组下标从0开始
int i = m - 1;
while(i <= n)
{
int j = m - 1;
while(j > 0 && s.at(i) == t.at(j)){
j--;
i--;
}
if(j == 0)
{
cout<<"字符串匹配成功,起始位置:"<<i + 1<<endl;
return i+1;
}
else i = i + dist(t,s.at(i));
}
return 0;
}
int main()
{
string s,t;
cout<<"请输入主串S:"<<endl;
cin>>s;
cout<<"请输入子串T:"<<endl;
cin>>t;
//调用BF算法进行字符串匹配
cout<<"BF算法:"<<endl;
cout<<BF(s,t)<<endl;
//调用KMP算法进行字符串匹配
cout<<"KMP算法:"<<endl;
cout<<KMP(s,t)<<endl;
//调用BM算法进行字符串匹配
cout<<"BM算法:"<<endl;
cout<<BM(s,t,s.size(),t.size())<<endl;
system("pause");
return 0;
}
算法设计--串匹配问题:BF算法、KMP算法、BM算法
最新推荐文章于 2022-03-25 23:31:37 发布