改代码为数据结构试验任务三:利用KMP算法实现查询主串中是否含有目标子串;
需要考虑DNA都是环状的,应用两个字符串实现环状结构。
#include <iostream>
#define MaxC 20
#define MaxE 20
using namespace std;
class Exp{ //定义样本类
private:
int used=0; //是否读取信息
char vir[MaxC]; //病毒DNA
char per[MaxC]; //人类DNA
int vsize; //病毒DNA串长度
int psize; //人类DNA串长度
public:
int getvsize(){ //获取病毒长度
return vsize;
}
int getpsize(){ //获取人类DNA长度
return psize;
}
void setVir(char* a){ //设定病毒DNA
int i=0;
while(a[i]!='\0'){
vir[i] = a[i];
i++;
}
vir[i] = '\0';
vsize = i;
used = 1;
}
void setPer(char* a){ //设定人类DNA
int i=0;
while(a[i]!='\0'){
per[i] = a[i];
i++;
}
per[i] = '\0';
psize=i;
used = 1;
}
char* getVir(){ //获取病毒DNA
return vir;
}
char* getPer(){ //获取人类DNA
return per;
}
int Used(){ //返回该样本是否有效
return used;
}
};
//函数声明
int KMP(char *sub,char* m ,int ns,int rm); //KMP检查子串是否在主串内
void Read(Exp *a); //读取样本数据
void PrintE(Exp *a); //打印样本数据
void Test(Exp *a); //进行样本检测
int KMP(char *sub,char *m,int ns,int nm){
int next[MaxC];
int j=0;
next[0] = 0;
next[1] = 0;
for(int i=2;i<ns;i++){
//总结 表示即为,若前字符的next位上的字符等于该字符,则该位为前next的值+1,否则为0
if(sub[i-1] == sub[next[i-1]])next[i] = next[i-1]+1;
else next[i] = 0;
}
for(int i=0;i<nm;i++){
//若母串的第i个数据与子串的第j个数据相同,则i++,j++
while(m[i]==sub[j]&&j<ns){
i++;
j++;
}
//出现母字符串中的元素成功与子字符串的最后 一个元素相同,则认为该字符串是母串的子串
if(j==ns)return 1;
//如果不同,则将j复位于next[j]的位置
j = next[j];
}
return 0;
}
//读取样本数据
void Read(Exp* a){
char v[MaxC],p[MaxC];
for(int i=0;;i++){
cout<<i+1<<":";
cin>>v>>p;
if(v[0]=='0'||p[0]=='0')break;
a[i].setVir(v);
a[i].setPer(p);
}
}
//打印样本数组
void PrintE(Exp* a){
for(int i=0;;i++){
if(a[i].Used()==1){
cout<<a[i].getVir()<<endl;
}else break;
}
}
//检查样本
void Test(Exp* a){
char *tmpv,*tmpp;
char test[MaxC*2];
int nv,np,flag=0;
char sub[MaxC];
for(int i=0;;i++){
//如果该样本已读取数据
if(a[i].Used()==1){
//基础赋值
flag = 0;
tmpv = a[i].getVir();
tmpp = a[i].getPer();
np = a[i].getpsize();
nv = a[i].getvsize();
//组成环状
for(int i=0;i<nv;i++){
test[i] = tmpv[i];
test[nv+i] = tmpv[i];
}
cout<<i+1<<":";
//拼接序列并检测子串
for(int i=0;i<nv;i++){
for(int j=0;j<nv;j++){
sub[j] = test[i+j];
}
sub[nv]='\0';
//KMP算法查询子串
if(KMP(sub,tmpp,nv,np)){ //结果为真
printf("Yes!\n");
flag=1; //标志无需再打印NO
break; //无需再查询
}
}
if(flag==0)
printf("No!\n"); //所有序列均不为子串,打印NO!
}else break;
}
}
int main(){
Exp *a = new Exp[MaxE]; //创建目标样本数组
cout<<"Input the exps and end with '0':\n";
Read(a); //读取样本信息
//PrintE(a); //打印样本数据(调试用)
printf("\n =================FZC=============== \n\n");
cout<<"Result:"<<endl;
Test(a); //进行检测
return 0;
}
改代码仅供参考,欢迎交流。