模式匹配算法
包括BF,KMP算法
模式匹配:子串的定位运算称为串的模式匹配或串匹配
BF(Brute Force)算法:穷举S的所有子串,判断是否与T匹配。
#include <iostream>
using namespace std;
#define Maxsize 100
typedef char SString[Maxsize + 1]; // 0 号单元存放串的长度
// BF 算法
// 求 T 在主串 S 中第 pos 个字符之后第一次出现的位置
// 其中,T 非空,1≤pos≤s[0],s[0]存放S串的长度
int Index_BF(SString s, SString T, int pos)
{
int i = pos, j = 1, sum = 0;
while (i <= s[0] && j <= T[0])
{
sum++;
if (s[i] == T[j]) // 如果相等,则继续比较后面的字符
{
i++;
j++;
}
else
{
i = i - j + 2; //i 退回到上一轮开始比较的下一个字符
j = 1; //j 退回到第1个字符
}
}
cout << "一共比较了" << sum << "次" << endl;
if (j > T[0]) // 匹配成功
return i - T[0]; // 返回匹配成功的位置
else
return 0;
}
// 求模式串 T 的 next 函数值
void get_next(SString T, int next[])
{
int j = 1;
int k = 0;
next[1] = 0;
while (j < T[0]) // T[0] 为模式串 T 的长度
{
if (k == 0 || T[j] == T[k])
next[++j] = ++k;
else
k = next[k];
}
cout << "-----next[]-----" << endl;
for (j = 1; j <= T[0]; j++)
cout << next[j] << " ";
cout << endl;
}
//计算next函数值改进算法
void get_next2(SString T, int next[])
{
int j = 1, k = 0;
next[1] = 0;
while (j < T[0])
{
if (k == 0 || T[j] == T[k])
{
j++;
k++;
if (T[j] == T[k])
next[j] = next[k];
else
next[j] = k;
}
else
k = next[k];
}
cout << "-----next[]-----" << endl;
for (j = 1; j <= T[0]; j++)
cout << next[j] << " ";
cout << endl;
}
// KMP 算法
// 利用模式串 T 的next 函数求 T 在主串 S 中第pos个字符之后的位置
// 其中,T 非空,1≤pos≤s[0],s[0]存放S串的长度
int Index_KMP(SString s, SString T, int pos, int next[])
{
int i = pos, j = 1,sum = 0;;
while (i <= s[0] && j <= T[0])
{
sum++;
if (j == 0 || s[i] == T[j])
{
i++;
j++;
}
else
j = next[j]; // 模式串向右移动
}
cout << "一共比较了" << sum << "次" << endl;
if (j > T[0])
return i - T[0];
else
return 0;
}
//生成一个其值等于chars的串T
bool StrAssign(SString& T, char* chars)
{
int i;
if (strlen(chars) > Maxsize)
return false;
else
{
T[0] = strlen(chars);
for (i = 1; i <= T[0]; i++)
{
T[i] = *(chars + i - 1);
cout << T[i] << " ";
}
cout << endl;
return true;
}
}
int main()
{
SString S, T;
char str[100];
cout << "串S:" << " ";
cin >> str; //aabaaabaaaabea
StrAssign(S, str);//可以修改程序,自己输入字符串
cout << "串T:" << " ";
cin >> str;//aaaab
StrAssign(T, str);
int* p = new int[T[0] + 1]; //生成T的next数组
cout << endl;
cout << "BF算法运行结果:" << endl;
cout << "主串和子串在第" << Index_BF(S, T, 1) << "个字符处首次匹配\n";
cout << endl;
cout << "KMP算法运行结果:" << endl;
get_next(T, p);
cout << "主串和子串在第" << Index_KMP(S, T, 1, p) << "个字符处首次匹配\n";
cout << endl;
cout << "改进的KMP算法运行结果:" << endl;
get_next2(T, p);
cout << "主串和子串在第" << Index_KMP(S, T, 1, p) << "个字符处首次匹配\n";
return 0;
}
字符串的应用
病毒检测
#include <iostream>
using namespace std;
#define Maxsize 100
typedef char SString[Maxsize + 1]; //0号单元存放串的长度
//生成一个其值等于chars的串T
bool StrAssign(SString& T, char* chars)
{
int i;
if (strlen(chars) > Maxsize)
return false;
else
{
T[0] = strlen(chars);//0号单元存放串的长度
for (i = 1; i <= T[0]; i++)
{
T[i] = *(chars + i - 1);
cout << T[i] << " ";
}
cout << endl;
return true;
}
}
//计算next函数值改进算法
void get_next2(SString T, int next[])
{
int j = 1, k = 0;
next[1] = 0;
while (j < T[0])
{
if (k == 0 || T[j] == T[k])
{
j++;
k++;
if (T[j] == T[k])
next[j] = next[k];
else
next[j] = k;
}
else
k = next[k];
}
}
// KMP 算法
// 利用模式串 T 的next 函数求 T 在主串 S 中第pos个字符之后的位置
// 其中,T 非空,1≤pos≤s[0],s[0]存放S串的长度
int Index_KMP(SString s, SString T, int pos)
{
int* next = new int[T[0] + 1]; // 生成T的next数组
get_next2(T, next);
int i = pos, j = 1;
while (i <= s[0] && j <= T[0])
{
if (j == 0 || s[i] == T[j])
{
i++;
j++;
}
else
j = next[j]; // 模式串向右移动
}
if (j > T[0])
return i - T[0];
else
return 0;
}
// 病毒检测
bool Virus_detection(SString S, SString T)
{
int i, j;
SString temp;//temp记录病毒变种
for (i = T[0] + 1, j = 1; j <= T[0]; i++, j++) //将T串扩大一倍,T[0]为病毒长度
T[i] = T[j];
for (i = 0; i < T[0]; i++)
{
temp[0] = T[0]; 病毒变种长度为T[0]
for (j = 1; j <= T[0]; j++)
temp[j] = T[i + j];
if (Index_KMP(S, temp, 1))
return 1;
}
return 0;
}
int main()
{
SString S, T;
char str[100];
cout << "患者DNA序列S:" << " ";
cin >> str;//eabbacab
StrAssign(S, str);
cout << "病毒DNA序列T:" << " ";
cin >> str;//aabb
StrAssign(T, str);
if (Virus_detection(S, T))
cout << "该患者已感染病毒!" << endl;
else
cout << "该患者未感染病毒!" << endl;
return 0;
}