#include<stdio.h>
#include<stdlib.h>
#include<string.h>
//状态码
#define OK 1
#define ERROR 0
#define TRUE 1
#define FALSE 0
#define EQ 0
#define GT 1
#define EQ 0 //相等
#define GT 1 //大于
#define LT -1 //小于
#ifndef _STATUS_H_ //如果系统已经定义下列宏 就不在重复定义
#define OVERFLOW -2 //堆栈上溢 超过所能表示的最大整数
#define UNDERFLOW -3 //堆栈下溢 超过所能表示的最小负数
#endif
typedef int Status;
#define MAX_SIZE 1024
/*typedef struct{
char ch[MAX_SIZE + 1]; //定长方式实现字符串 (浪费空间)
int length;
}SString;*/
//使用指针实现
//串的堆式顺序存储结构(Beap)
typedef struct {
char * ch; //如果是非空串 按照需要长度分配内存
int length; //串的当前长度 length代替'\0'的作用
}HString;
void InitString_HeapString(HString * str){
str->ch = NULL;
str->length = 0;
}
void PrintHeapString(HString * str){
if(str->length == 0 || !str->ch){
printf("堆字符串为空!\n");
return ;
}
for(int i = 0; i < str->length; i++){
printf("%c",str->ch[i]);
}
}
//为串赋值 值为字符串首地址chars
Status StrAssign_HeapString(HString * str, char * chars){
int len = strlen(chars);
if(!len){
return ERROR;
}
InitString_HeapString(str);
str->ch = (char *)malloc(len * sizeof(char));
if(!str->ch){
exit(OVERFLOW);
}
for(int i = 0; i < len; i++){
str->ch[i] = chars[i];
}
str->length = len;
return OK;
}
/*部分匹配函数的实现*/
void Get_Next(HString child, int * next){
int i =0;
int j =-1;
next[0]= -1; //不会用到
while(i< child.length){
if(j == -1 || child.ch[i] == child.ch[j]){
++i;
++j;
next[i] = j;
}else{
j = next[j];
}
}
}
/*KMP匹配算法*/
int KMPCompare(HString parent, HString child, int pos){
int next[255];
Get_Next(child, next);
int i =pos - 1;
int j =0; //j用于子串child中的起始位置
while(i< parent.length && j < child.length){
if(j == 0 || parent.ch[i] == child.ch[j]){
++i;
++j;
}else{
j = next[j]; //i不变,j后退
}
}
if(j ==child.length){
return (i + 1) - j;
}
return 0;
}
//检测病毒感染返回1表示感染 返回0表示未感染
int Virus_Check(HString parent , HString child)
{
//char tempVirus[child.length * 2 + 1]; //预留一个位置给'\0' 这个位置注意不可以直接定义数组 来开辟空间 因为编译时 child.length未赋值导致 无法得到数组大小
char * tempVirus = (char *)malloc((child.length * 2 + 1) * sizeof(char));
for(int i = 0 ; i < child.length * 2 ; i++){
tempVirus[i] = child.ch[i % child.length];
}
tempVirus[child.length * 2 ] = '\0';
for(i = 0 ; i < child.length ; i++){
char * virus = (char *)malloc((child.length + 1) * sizeof(char));
for(int j = i ; j < i + child.length ; j++)
{
virus[j - i] = tempVirus[j];
}
virus[child.length] = '\0';
//将virus转换为堆串比较
HString virus_h;
InitString_HeapString(&virus_h);
StrAssign_HeapString(&virus_h , virus);
if(KMPCompare(parent , virus_h , 1) != 0)
return 1;
}
return 0;
}
void main(){
/*使用KMP算法检测人类是否感染病毒*/
//人类DNA
char * person [] = {
"bbaabbba","aaabbbba","abceaabb","abaabcea","cdabbbab",
"cabbbbab","bcdedbda","bdedbcda","cdcdcdec","cdccdcce"
};
//病毒DNA
char * virus [] = {
"baa","bae","aabb","abcd","aacd",
"abcde","acc","cde","cced","aace"
};
//保存DNA
HString persons_h[10];
HString virus_h [10];
for(int i = 0 ; i < 10 ; i++)
{
InitString_HeapString(&persons_h[i]);
InitString_HeapString(&virus_h[i]);
StrAssign_HeapString(&persons_h[i],person[i]);
StrAssign_HeapString(&virus_h[i],virus[i]);
}
//检测
for(i = 0 ; i < 10 ; i++)
{
for(int j = 0 ; j < 10 ; j++)
{
if(Virus_Check(persons_h[i] , virus_h[j]))
printf("检测样本DNA:%s\t匹配的病毒:%s\n", person[i] , virus[i]);
}
}
}