数据结构---病毒检测和计数字符频度
案例分析与实现
病毒感染检测
分析:检测病毒DNA序列是否在患者DNA序列里出现过,实际上就是字符串的模式匹配问题,这里假设病毒 DNA 序列的长度是 m, 因为病毒 DNA 序列是环状的 ,所以将病毒的DNA连续存储2次(为了线性取得长度为m的模式串),在调用匹配算法时需要循环操作m次(这里可以看作长度为m的病毒DNA中每一个都作为一次序列的开头,这样就有m种),匹配成功就终止循环。
算法步骤
-
从文件中读取待检测的任务数 num。
-
依次检测每对病毒DNA和人的DNA是否匹配,循环 num次,执行以下操作:
- 从文件中分别读取一对病毒DNA序列和人的DNA序列;
- 设置一个标志性变量flag, 用来标识是否匹配成功,初始为0, 表示未匹配;
- 病毒DNA序列的长度是 m, 将存储病毒DNA序列的字符串长度扩大为 2m, 将病毒DNA序列连续存储两次;
-
循环m次,重复执行以下操作:
- 依次取得每个长度为m的病毒DNA环状字符串;
- 将此字符串作为模式串,将人的DNA序列作为主串, 调用BF算法进行模式匹配,将匹配结果返回赋值给flag;
- 若flag非0, 表示匹配成功, 中止循环,表明该人感染了对应的病毒。
-
退出循环时, 判断flag的值,若flag非0, 输出 "YES" , 否则,输出 "NO"。
算法实现
void Virus_detection()
{
int num, m, flag, i, j;
SString Virus, Person, temp,Vir;
ifstream inFile("病毒感染检测输入数据.txt");
ofstream outFile("病毒感染检测输出结果.txt");
inFile >> num;//读取待检测的任务数
while (num--) //依次检测每对病毒DNA和人的DNA是否匹配
{
inFile >> Virus.ch + 1;//读取病毒DNA序列
inFile >> Person.ch + 1;//读取人的DNA序列
Vir=Virus;//将病毒的DNA暂时存在Vir中,以备输出
Virus.length = strlen(Virus.ch) - 1;
Person.length = strlen(Person.ch) - 1;
flag = 0;//用来标识是否匹配,初始为0,匹配后为非0
m = Virus.length;
for (i = m + 1, j = 1; j <= m; j++)//因病毒为环状,故将病毒的长度扩大2倍
Virus.ch[i++] = Virus.ch[j];//即可线性取到所有长度为Virus.len的字符串
Virus.ch[2 * m + 1] = '\0';//添加结束符号
for (i = 0; i < m; i++)
{
for (j = 1; j <= m; j++) temp.ch[j] = Virus.ch[i + j];
//取长为Virus.len的环形字符串
//即Virus.ch[0]-- Virus.ch[Virus.len-1],
//Virus.ch[1]-- Virus.ch[0], Virus.ch[2]-- Virus.ch[1]...
temp.ch[m + 1] = '\0'; //添加结束符号
temp.length = strlen(temp.ch) - 1;
flag = Index_BF(Person, temp, 1); //模式匹配
if (flag) break; //匹配即可退出循环
}
if (flag)
outFile << Vir.ch+ 1 << " " << Person.ch + 1 << " " << "YES" << endl;
else
outFile << Vir.ch + 1 << " " << Person.ch + 1 << " " << "NO" << end;
统计不同字符出现的频度
分析:字母长度为26,数字符号有10个,所以可用一个长度为26的整型数组来分明存储字符和数字符号出现的次数,然后新建一个只读不可写的文件将结果存入。
算法实现
void count()
{
int times[36];
char ch;
int num;
for(int i=0;i<36;i++)
{
times[i]=0;//将计数次数的数组初始值均赋值为0
}
cout<<"请输入字符"<<endl;
cin>>ch;
while(ch != '#')//'#'用于标志字符串的结束
{
if(ch >= '0' && ch <= '9')//times[0]~times[9]用于记录'0'~‘9’的频度
{
num = ch - '0';//数组下标和存储的值是一一对应的
times[num]++;
}
else if(ch >= 'A' && ch <= 'Z')//times[10]~times[35]用于记录A到Z的频度
{
num = ch - 'A' + 10;//存字符的数组下标是从10开始的
times[num]++;
}
else
{
cout<<"输入字符错误!"<<endl;
}
cin>>ch;
}
for(int j = 0; j < 36; j++)//输出输入字符串的频度值
{
cout<<times[j];
}
}