问题描述:
医学研究者最近发现了某些新病毒,通过对这些病毒的分析,得知它们的 DNA 序列都是环状的。现在研究者已收集了大量的病毒DNA和人的DNA数据,想快速检测出这些人是否感染了相应的病毒。为了方便研究,研究者将人的DNA和病毒DNA均表示成由一些字母组成的字符串序列,然后检测某种病毒DNA序列是否在患者的DNA序列中出现过,如果出现过,则此人感染了该病毒,否则没有感染。例如,假设病毒的DNA序列为baa,患者1的DNA序列为aaabbba ,则感染;患者2的 DNA序列为 babbba,则未感染。(注意,人的DNA序列是线性的,而病毒的DNA序列是环状的。)
输入要求:
多组数据,每组数据有1行,为序列A和B,A对应病毒的 DNA序列,B对应人的 DNA序列。A和B都为“0”时输入结束。
输出要求:
对于每组数据输出1行,若患者感染了病毒输出“YES”,否则输出“NO”。
输入样例:
abbab abbabaab
baa cacdvcabacsd
abc def
0 0
输出样例:
YES
YES
NO
//KMP求解基于字符串模式匹配算法的病毒感染检测
#include <stdio.h>
#include<iostream>
#include <string.h>
#define _CRT_SECURE_NO_WARNINGS
#define maxsize 100
using namespace std;
void Nextval(char T[], int* next)//next函数修正
{
int lenT = strlen(T);
int k = -1;//前缀
int j = 0;//后缀
next[0] = -1;
while (j < lenT)
{
if (k == -1 || T[j] == T[k])
{
j++;
k++;
if (T[j] != T[k])
{
next[j] = k;
}
else
{
next[j] = next[k];
}
}
else
{
k = next[k];
}
}
}
int KMP(char S[], char T[])
{
int i, j, lenS, lenT,t[1];
lenS = strlen(S);
lenT = strlen(T);
int re,flag=0;
re = lenT+1;
int next[maxsize];
while (re--)
{
i = 0; j = 0;
for (int m = 0; m < lenT; m++)
{
Nextval(T, next);
while (i < lenS && j < lenT)
{
if (j == -1 || S[i] == T[j])
{
i++;
j++;
}
else
{
j = next[j];
}
}
}
if (j == lenT)//匹配成功,不需要考虑位置返回0
{
return 0;
}
else//匹配失败,模式串更换次序
{
t[0] = T[0];
for (int k = 0; k < lenT - 1; k++)
{
T[k] = T[k + 1];
}
T[lenT - 1] = t[0];
}
}
return -1;
}
int main()
{
char S[maxsize], T[maxsize];
int target[maxsize],i=0;
while (1)
{
cin >> T; cin >> S;
if (!strcmp(S,"0") && !strcmp(T, "0")){//停止输入
break;
}
target[i] = KMP(S, T);//存储匹配结果
i++;
}
for (int j=0;j<i;j++)//结果输出
{
if (target[j] == -1)
cout << "NO\n";
else
cout << "Yes\n";
}
return 0;
}
验证:
输入:
abbab abbabaab
baa cacdvcabacsd
abc def
0 0
输出结果如下图所示: