概念
模式匹配是数据结构中字符串的一种基本运算,给定一个子串,要求在主串中找出与该子串相同的所有子串,这就是模式匹配。
BF算法
BF算法,即暴力(Brute Force)算法,是普通的模式匹配算法,BF算法的思想就是将目标串S的第一个字符与模式串T的第一个字符进行匹配,若相等,则继续比较S的第二个字符和 T的第二个字符;若不相等,则比较S的第二个字符和T的第一个字符,依次比较下去,直到得出最后的匹配结果。BF算法是一种蛮力算法。
线性病毒
环状病毒
依次检测病毒DNA和人的DNA是否匹配,循环执行:
l
分别读取病毒
DNA
序列和人的
DNA
序列;
l
设置
flag
,初始为
0
,表示未匹配;
l
病毒
DNA
长度是
m
,连续存储两次扩大为
2m
;
l
循环
m
次,重复执行以下操作:
Ø
依次取得每个长度为
m
的病毒
DNA
环状字符串;
Ø
将此字符串作模式串,将人的
DNA
作主串,调用
BF
,将结果返回
flag
;
Ø
若
flag
非
0
,表示匹配成功。
l
退出循环时,若
flag
非
0
,输出“
YES
”,否则,输出“
NO
”。
废话不多说直接上代码,我称它为BFPro算法
#include<string.h> /*是在程序编译之前要处理的内容,与字符串的调用有关,常用函数包括strlen(求字符串长度)、strcmp(比较两个字符串是否一样)和strcat(字符串连结操作)等*/
#include<stdio.h>
#define OK 1
#define ERROR 0
#define OVERFLOW -2
#define MAXSTRLEN 255 //用户可在255以内定义最长串长
typedef char SString[MAXSTRLEN+1]; //0号单元存放串的长度
//初始化字符数组
int StrAssign(SString T,char *chars){
size_t i;
if(strlen(chars)>MAXSTRLEN){
return ERROR;
}else{
T[0] = strlen(chars); // 将字符串长度存储在 T[0] 中
for (i=1; i < strlen(chars)+1; i++) { // 在循环中复制每个字符
T[i] = *(chars + i - 1);
}
T[i] = '\0'; // 在字符串末尾添加空字符
return OK; // 返回操作成功
}
}
//BF算法
int BF(SString S,SString T,int pos){
int i=pos,j=1;
while(i<=S[0] && j<=T[0]){
if(S[i]==T[j]){
i++;
j++;
}else{
i=i-j+2;
j=1;
}
}
if(j>T[0]){
return i-T[0];
}else{
return 0;
}
}
//复制子串
//需要两个参数,一个是复制的字符数组,另一个是字符串变量的长度
void CopyNewArray(SString T,int length) {
//创建一个临时数组,用来存储当前的字符串
char temp[length];
//将要复制的字符数组长度变为2倍加1,因为数组第0位存储长度
T[0] = length*2+1;
//将字符数组复制给temp临时字符数组
for (int i = 0; i <=length; i++) {
temp[i] = T[i+1];
}
//将temp数组中的元素添加到复制的字符数组中
for (int i = length+1; i <=2 * length+1; i++) {
T[i] = temp[i -length-1];
}
}
//模式匹配环状病毒,BFPro,传入三个参数,主串,病毒串,病毒串长度
//病毒长度用于计量一次取出多少个元素
int BFPro(SString S,SString T,int length){
//flag标志位
int flag=0;
//temp临时数组,存储每次需要比较的字符,长度为length,temp[0]存储长度
char temp[length]={length};
//定义一个索引下标,只来指向T数组的字符下标,初始下标为1,因为T[0]存储的是长度
int index = 1;
//循环取出需要需要比较的字串,并调用BF算法进行比较
//循环终止条件是索引下标于T数组的长度
while (index <= length * 2) {
// 从数组T中取出m个元素给temp
for (int i = 1; i <length+1; i++) {
//先取出第一个,后将索引下标自增
temp[i] = T[index++];
}
//输出temp数组中存储的元素
printf("目标子串为:");
for(int i=1;i<length+1;i++){
printf("%c",temp[i]);
}
printf("\n");
//判断是否取到了T数组的最后一位
//如果没取到最后一位就将索引下标后移一位,重新取出length个元素,以便于循环继续
if(index<=length*2){
index=index-length+1;
}
//调用BF算法,将temp数组与主串进行比较,返回值赋给flag
flag=BF(S,temp,1);
//判读返回值是否为0,不为零即找在主串中找到了字串,返回flag子串在主串中出现的位置
if(flag!=0){
return flag;
}
}
//如果循环结束后还没有返回flag,就表示子串没有出现在主串中,返回0
return flag;
}
int main()
{
int i;
SString S,T;
StrAssign(S,"bcaCaebbpaba") ;
StrAssign(T,"bcb");
int length=T[0];
printf("主串是:");
for (i = 1; i <= S[0]; i++){
printf("%c",S[i]);
}
printf("\n");
printf("子串是:");
for (i = 1; i <= T[0]; i++){
printf("%c",T[i]);
}
printf("\n\n");
//调用CopyNewArray方法复制子串
CopyNewArray(T, length);
printf("新的子串是:");
//输出复制后的子串
for (i = 1; i <= T[0]; i++){
printf("%c",T[i]);
}
printf("\n\n");
//调用BFPro方法进行比较,将返回值赋值给flag
int flag=BFPro(S,T,length);
//判断flag的值,如果不为0,表示子串出现在主串中,患者感染,感染位为flag
//否则未感染
if(flag){
printf("该患者已感染病毒。主串(患者DNA)和子串(病毒DNA)在第%d个字符处首次匹配",flag);
}else{
printf("患者未感染病毒!");
}
}