查找子串
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;
}