【数据结构实验】病毒检测问题——字符串模式匹配BF算法

目录

实验目的

实验内容(题目)

实验环境 

程序代码 

实验分析 


实验目的

  1. 掌握字符串的顺序存储表示方法。
  2. 掌握字符串模式匹配算法BF算法的实现。

实验内容(题目)

       医学研究者最近发现了某些新病毒,通过对这些病毒的分析,得知它们的DNA序列都是环状的。现在研究者已收集了大量的病毒DNA和人的DNA数据,想快速检测出这些人是否感染了相应的病毒。为了方便研究,研究者将人的DNA和病毒DNA均表示成由一些字母组成的字符串序列,然后检测某种病毒DNA序列是否在患者的DNA序列中出现过,如果出现过,则此人感染了该病毒,否则没有感染。例如,假设病毒的DNA序列为baa,患者1的DNA序列为aaabbba,则感染;患者2的 DNA序列为babbba,则未感染。(注意:人的DNA序列是线性的,而病毒的DNA序列是环状的。)


实验环境 

(1)软件系统

操作系统:Windows 10

编程环境:Embarcadero Dev-C++ 6.3,包含GNU GCC编译器和GDB调试器

(2)硬件系统

CPU:Intel(R) Core(TM) i7-10875H CPU @ 2.30GHz

内存:16GB

硬盘:500GB SSD


程序代码 

#include <stdio.h> // 标准输入输出头文件
#include <string.h> // 字符串操作头文件

#define YES 1
#define NO  0

// 全局变量定义
char V[20];  // 存储病毒DNA序列的数组
char D[20];  // 存储人类DNA序列的数组

// 使用暴力匹配算法进行字符串匹配的函数
int BF(char *D, char *V) {
    int i = 0, j = 0; // i是主字符串的索引,j是模式字符串的索引
    // 遍历主字符串D和模式字符串V
    while (i < strlen(D) && j < strlen(V)) {
        if (D[i] == V[j]) { // 如果当前字符匹配
            i++; 
            j++;
        } else { // 如果字符不匹配
            i = i - j + 1; // 主字符串回溯
            j = 0; // 模式字符串重置
        }
    }
    // 如果模式字符串V完全匹配,返回YES
    if (j >= strlen(V)) return YES;
    // 否则,返回NO
    else return NO;
}

// 处理环状DNA序列的函数,利用循环展开来匹配
int BFjudge(char *D, char *V) {
    int flag = NO; // 默认匹配标志为NO
    int i, j, m;
    char temp[20]; // 临时存储展开的环状DNA序列
    m = strlen(V); // 获取模式字符串V的长度
    // 将模式字符串V复制到其末尾,形成循环展开的字符串
    for (i = m, j = 0; j < m; j++) {
        V[i++] = V[j];
    }
    V[2 * m] = '\0'; // 确保字符串以null字符终止
    
    // 遍历循环展开的字符串
    for (i = 0; i < m; i++) {
        // 构建当前子串temp
        for (j = 0; j < m; j++) {
            temp[j] = V[i + j];
        }
        temp[m] = '\0'; // 确保子串以null字符终止
        
        // 使用BF算法进行匹配
        flag = BF(D, temp);
        if (flag) break; // 如果匹配成功,退出循环
        else if (i >= m) return NO; // 如果超过了环状DNA序列的长度,返回NO
    }
    return flag ? YES : NO; // 返回匹配结果
}

// 输入和输出处理函数
int PRINThand() {
    int i = 0, k = 0;
    int s[20]; // 存储匹配结果的数组

    printf("请输入病毒DNA及人的DNA(输入0 0结束):\n");
    while (1) {
        scanf("%19s", V); // 读取病毒DNA序列
        scanf("%19s", D); // 读取人类DNA序列
        if (V[0] == '0' && D[0] == '0') break; // 检测到输入为'0 0'则结束循环
        
        // 调用BFjudge函数并存储结果到数组s
        s[k] = BFjudge(D, V);
        k++; // 结果数组索引递增
    }

    // 根据结果数组s输出所有匹配结果
    printf("病毒感染检测输出结果:\n");
    for (i = 0; i < k; i++) {
        printf("%s\n", s[i] == YES ? "YES" : "NO");
    }
    return 0; // 函数返回0表示成功执行
}

// 主函数
int main() {
    PRINThand(); // 调用输入和输出处理函数
    return 0; // 程序结束,返回0
}

实验分析 

从以下方面分析:

1、正确性(输入的测试数据和测试结果,附测算截屏)

这个程序的目的是为了检测人类DNA序列中是否存在特定的病毒DNA序列。程序使用暴力匹配(Brute Force, BF)算法来找出模式字符串(这里是病毒DNA)是否在主字符串(人类DNA)中。

测算截屏:

2、可读性(主要在源代码中体现)

  • 代码结构清晰,具有明确的模块划分。
  • 函数命名合理,符合其功能。
  • 注释充分,有助于理解代码逻辑。

3、健壮性(容错性,主要在源代码中体现,在此简要说明)

  • 优点:
    • 检查了结束输入的条件(当用户输入"0 0"时)。
    • 使用了%19s来限制scanf读取的字符数,避免了缓冲区溢出。
  • 缺点:
    • 程序没有处理异常输入或非预期的情况,如非数字字符输入、过长的DNA序列或空字符串。
    • 因为使用了全局变量,程序的健壮性受限,容易被意外的修改影响。

4、时间和空间复杂度(针对核心算法函数分析)

  • 时间复杂度:暴力匹配算法的时间复杂度是O(n*m),其中n是主字符串的长度,m是模式字符串的长度。在最坏的情况下,每个字符都要比较一次,所以是n和m的乘积。在BFjudge中,我们对于长度为m的模式字符串,最多做了m次匹配尝试,每次都是O(m)的时间复杂度,因此整体是O(m^2)。
  • 空间复杂度程序使用固定大小的数组(20个字符),所以空间复杂度为O(1),也就是常数空间。temp数组在BFjudge函数中用于存储循环展开后的字符串,长度也是固定的。

实验到此结束!

点赞关注,获取更多干货~

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Frank牛蛙

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值