利用串的各种模式匹配算法实现病毒感染检测
目录
一、实验目的
1.了解串的基本概念和操作。
2.掌握顺序串的实现方法。
3.掌握串的模式匹配算法
4.利用顺序串实现病毒感染检测
二、实验内容
利用顺序串实现串的各种模式匹配算法。研究者将人的DNA和病毒DNA均表示成由一些字母组成的字符串序列。然后检测某种病毒DNA序列是否在患者的DNA序列中出现过,如果出现过,则此人感染了该病毒,否则没有感染。例如,假设病毒的DNA序列为t=“baa”,患者1的DNA序列为s1=“aaabbaaba”,则感染,患者2的DNA序列为s2=“babbbabcabb”,则未感染。请你编写实现病毒感染检测。
三、实验设备与环境
1.Windows11
2.Codeblocks
四、实验设计方案
实验步骤:
1.数据预处理:
(1)读取病毒DNA序列和患者DNA序列。
(2)去除输入字符串中的空格和其他非字母字符。
(3)将所有字符串转换为小写字母。
2.朴素模式匹配算法实现:
(1)定义函数,其中s是患者的DNA序列,p是病毒的DNA序列。
(2)使用两个指针i和j分别指向字符串s和p的起始位置。
(3)循环遍历字符串s和p,比较对应位置的字符是否相等。如果相等,则将指针j后移一位;否则,将指针i后移一位。
(4)如果指针j到达字符串p的末尾,说明字符串p在字符串s中出现了,返回True;否则返回False。
3.KMP算法实现:
(1)定义函数kmp_match(s, p),其中s是患者的DNA序列,p是病毒的DNA序列。
(2)创建一个辅助数组(或称为“部分匹配表”)来存储字符串p的部分匹配信息。
(3)使用两个指针i和j分别指向字符串s和p的起始位置。
(4)循环遍历字符串s和p,比较对应位置的字符是否相等。如果相等,则将指针j后移一位;否则,根据部分匹配表的信息移动指针i。
(5)如果指针j到达字符串p的末尾,说明字符串p在字符串s中出现了,返回True;否则返回False。
4.病毒感染检测:
(1)对于每组病毒DNA序列和患者DNA序列,调用朴素模式匹配算法和KMP算法进行匹配。
(2)比较两种算法的执行时间和结果,输出患者是否感染该病毒。
5.结果分析:
(1)分析实验结果,包括不同算法的时间复杂度和空间复杂度,以及在实际数据上的表现。
(2)编写完整的程序文档,包括算法描述、数据结构、输入输出格式等。
设计思想与算法描述
1.设计思想:
本实验旨在通过实现两种常见的模式匹配算法(朴素模式匹配算法和KMP算法)来检测病毒感染。通过比较两种算法的性能,我们可以更好地理解它们在实际问题中的应用。在实现算法时,需要注意时间复杂度和空间复杂度的控制,以提高程序的效率。此外,考虑到DNA序列的特点,我们需要选择适合的字符串匹配算法来确保程序的正确性和效率。
2.算法描述:
朴素模式匹配算法:该算法通过逐个比较字符串中的字符来确定模式是否出现。它的时间复杂度为O(n*m),其中n是主字符串的长度,m是模式字符串的长度。空间复杂度为O(1)。具体实现时,可以使用双指针技术进行字符比较和位置移动。
KMP算法:该算法通过利用已经匹配的信息来优化匹配过程。它的时间复杂度为O(n+m),其中n是主字符串的长度,m是模式字符串的长度。空间复杂度为O(m)。具体实现时,需要创建一个部分匹配表来存储模式字符串的部分匹配信息。在匹配过程中,根据部分匹配表的信息进行指针移动,以提高匹配效率。
3.开发流程:
首先进行数据预处理,包括去除空格和非字母字符、转换为小写字母等操作。然后分别实现朴素模式匹配算法和KMP算法,并编写病毒感染检测程序。在实现过程中,需要注意代码的可读性和可维护性,同时进行必要的错误处理和边界检查。最后进行测试与验证,选择多组病毒DNA序列和患者DNA序列作为测试数据,比较两种算法的执行时间和结果,验证程序的正确性和效率。同时分析实验结果,编写完整的程序文档。
五、实验结果
六、附录
#include <stdio.h>
#include <string.h>
#define MaxSize 100
typedef struct
{
char data[MaxSize]; // 定义可容纳MaxSize个字符的空间
int length; // 标记当前实际串长
}SqString;
/*---------------------------简单匹配算法-------------------------------*/
int Index(SqString s, SqString t)
{
int i = 0;
int j = 0;
int k;
while((i < s.length) && (j < t.length))
{
if(s.data[i] == t.data[j]) // 继续匹配下一个字符
{
i++;
j++;
}
else // 主串/子串指针回溯重新开始下一次匹配
{
i = i - j + 1;
j = 0;
}
}
if(j >= t.length) // 返回匹配的第一个字符的下标
k = i - t.length;
else // 模式匹配不成功
k = -1;
return k;
}
/*-----------------------------由模式串t求出next值-------------------------------*/
void GetNext(SqString t, int next[])
{
int j;
int k;
j = 0;
k = -1;
next[0] = -1;
while(j < t.length - 1)
{
if((k == -1) || (t.data[j] == t.data[k]))
{
j++;
k++;
next[j] = k;
}
else
{
k = next[k];
}
}
}
/*-----------------------------由模式串t求出nextval值-------------------------------*/
void GetNextval(SqString t, int nextval[])
{
int j;
int k;
j = 0;
k = -1;
nextval[0] = -1;
while(j < t.length)
{
if((k == -1) || (t.data[j] == t.data[k]))
{
j++;
k++;
if(t.data[j] != t.data[k])
nextval[j] = k;
else
nextval[j] = nextval[k];
}
else
{
k = nextval[k];
}
}
}
int KMPIndex(SqString s, SqString t)
{
int next[MaxSize];
int i = 0;
int j = 0;
int v;
GetNext(t, next);
while((i < s.length) && (j < t.length))
{
if((j == -1) || (s.data[i] == t.data[j]))
{
i++;
j++; // i,j各增1
}
else
j = next[j]; // i不变,j后退
}
if(j >= t.length)
v = i - t.length; // 返回匹配模式串的首字符下标
else
v = -1; // 返回不匹配标志
return v;
}
int KMPIndex1(SqString s, SqString t)
{
int nextval[MaxSize];
int next[MaxSize];
int i = 0;
int j = 0;
int v;
GetNextval(t, next);
GetNextval(t, nextval);
while((i < s.length) && (j < t.length))
{
if((j == -1) || (s.data[i] == t.data[j]))
{
i++;
j++; // i,j各增1
}
else
j = nextval[j];
}
if(j >= t.length)
v = i - t.length; // 返回匹配模式串的首字符下标
else
v = -1; // 返回不匹配标志
return v;
}
/*---------------------------由串常量cstr创建串str-------------------------------*/
void StrAssign(SqString &str, char cstr[])
{
int i;
for(i = 0; cstr[i] != '\0'; i++)
str.data[i] = cstr[i];
str.length = i;
}
/*---------------------------输出串s的所有元素-------------------------------*/
void DispStr(SqString s)
{
int i;
if(s.length > 0)
{
for(i = 0; i < s.length; i++)
printf("%c", s.data[i]);
printf("\n");
}
}
int main(void)
{
int j;
int next[MaxSize], nextval[MaxSize];
SqString s, t;
StrAssign(s, " aaabbaaba ");
StrAssign(t, " babbbabcabb ");
printf("串s:");
DispStr(s);
printf("串t:");
DispStr(t);
printf("简单匹配算法:\n");
printf(" t在s中的位置=%d\n", Index(s, t));
GetNext(t, next); // 由模式串t求出next值
GetNextval(t, nextval); // 由模式串t求出nextval值
printf(" j ");
for(j = 0; j < t.length; j++)
printf("%4d", j);
printf("\n");
printf(" t[j] ");
for(j = 0; j < t.length; j++)
printf("%4c", t.data[j]);
printf("\n");
printf(" next ");
for(j = 0; j < t.length; j++)
printf("%4d", next[j]);
printf("\n");
printf(" nextval ");
for(j = 0; j < t.length; j++)
printf("%4d", nextval[j]);
printf("\n");
printf("KMP算法:\n");
printf(" t在s中的位置=%d\n", KMPIndex(s, t));
printf("改进的KMP算法:\n");
printf(" t在s中的位置=%d\n", KMPIndex1(s, t));
return 0;
}