使用c++ stl库 实现王卓老师数据结构课上病毒匹配算法 KMP解法

#include <iostream>
using namespace std;
#include <vector>
#include <string>
#include <set>

#define N 10

//一个字符串的类 存放主串模式串
class HString{
public:
    string ch;//主串模式串内容
    int length;//主串模式串长度

    HString()
    {
        ch=" ";
        length=0;
    }
};

vector<int> Get_Next(const HString& child)
{
    int i=0;
    int j=-1;
    vector<int> next(child.length+1,-1);

    while(i<child.length)
    {
        //匹配成功或者特殊情况 继续算下一个位置的next值
        if(j==-1 || child.ch[i]==child.ch[j])
        {
            i++;
            j++;
            next[i]=j;
        }
        //匹配失败 继续找前缀的前缀匹配
        else
        {
            j=next[j];
        }
    }
    return next;
}

int KMP_compare(const HString& parent,const HString& child)
{
    //KMP核心 next数组
    //可以返回一个vector<int>类型 传入的是一个HString类
    vector<int> next=Get_Next(child);

    int i=0;
    int j=0;

    while(i<parent.length && j<child.length)
    {
        //如果匹配成功或者特殊情况 继续向前匹配
        if(j==0 || parent.ch[i]==child.ch[j])
        {
            i++;
            j++;
        }
        else
        {
            j=next[j];
        }
    }

    if(j==child.length)
    {
        return i-child.length+1;
    }
    else
    {
        return 0;
    }
}

//用父子串命名
bool Virus_Check(const HString& parent,const HString& child)
{
    //首先解决什么与什么比较的问题
    //m长度的病毒串去比较n长度的人类串 问题在于 一条病毒串有很多种情况(DNA循环结构)
    //可以将病毒串复制一份 接在原串的后面 这样一来 去依次截取固定长度 就能实现所有情况都找到

    //用一个新变量存放胶合后的串
    string tempVirus;

    //实现复制 胶合
    for(int i=0;i<child.length*2;i++)
    {
        //i%child.length 取值在0~length-1
        //巧妙地使i在有效下标循环
        tempVirus+=child.ch[i%child.length];
    }

    //然后就是从这个胶合出的串去 取出原病毒串长度的模式串
    //举个例子吧 对于病毒串ABB来说 其实有ABB BBA BAB 三种情况
    //变成 ABBABB后 从0取三 得ABB 从1取三 得BBA 从2取三 得BAB
    //实现这个过程
    for(int i=0;i<child.length;i++)
    {
        //一行代码搞定
        string virus=tempVirus.substr(i,child.length);

        //取完后 把这些都放在HString类中去 因为比较还是得用两个HString比
        HString virus_h;
        virus_h.ch=virus;
        virus_h.length=virus.length();

        //直接在这里比就行了 省的再遍历取出 然后比 多此一举
        //传入主串 模式串 也就是const HString& 返回值应该为int 找到了会是一个具体数 可以用来判断
        if(KMP_compare(parent,virus_h)!=0)
        {
            return true;
        }
    }
    return false;
}


int main() {

    //设置要比对的内容
    //人类dna 用string容器
    //使用了define 这里就可以任意修改数量
    const string person[]={
            "bbaabbba","aaabbbba","abceaabb","abaabcea","cdabbbab",
            "cabbbbab","bcdedbda","bdedbcda","cdcdcdec","cdccdcce"
    };
    //病毒DNA
    const string virus[] = {
            "baa","bae","aabb","abcd","aacd",
            "abcde","acc","cde","cced","aace"
    };

    //把他们依次存放进Hstring类中 之后比较
    //因为数量较多 使用vector容器 将HString类型的数据存储
    //声明空间需要N单元
    vector<HString> person_h(N);
    vector<HString> virus_h(N);

    //放入容器
    for(int i=0;i<N;i++)
    {
        person_h[i].ch=person[i];
        person_h[i].length=person[i].length();

        virus_h[i].ch=virus[i];
        virus_h[i].length=virus[i].length();
    }


    set<pair<string, string>> outputSet; // 用于跟踪已输出的结果

    //需要比较的是人DNA和病毒DNA的每一项
    //也就是全要比一遍 使用两层遍历
    for(int i=0;i<N;i++)
    {
        for(int j=0;j<N;j++)
        {
            if (Virus_Check(person_h[i], virus_h[j]))
            {
                // 使用pair来表示匹配的样本DNA和匹配的病毒
                pair<string, string> resultPair(person_h[i].ch, virus_h[j].ch);

                // 检查是否已经输出过相同的结果
                if (outputSet.find(resultPair) == outputSet.end()) {
                    cout << "检测样本DNA:" << resultPair.first << "\t匹配的病毒:" << resultPair.second << endl;
                    outputSet.insert(resultPair); // 添加到集合中
                }
            }
        }
    }

    return 0;
}
 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值