摘要
经过对字母序列配比对算法的研究,探索最优解动态规划,BF算法在全局比对和局部比对中的引用以及算法的实现过程。针对此问题,我们提出了第一阶段(由于文本中没有空格和符号,我们将利用回车进行分组)的解决方案如下:第一种情况假设容错率为0时,通过动态规划算法和得分矩阵来算出匹配的最佳得分,首先需要先进行定义,建立得分矩阵,然后通过公式来填充矩阵,然后需要选择路径,在用最佳得分的路径来找到最佳的匹配字符串;第二种情况假设字符串存在容错率且不为0,通过BF算法用来将主串和子串进行对比检测,首先先用子串的首字母和主串的进行比较,然后将子串从左至右进行移动,一旦发现超过容错率,那就使指针重新开始(BF算法直接重新开始)若在容错范围内,则会继续比较下去,直到比较完成或者超出容错范围。在本文中,第一阶段的匹配结果我们已经成功实现,并可以广泛应用于生物学遗传DNA序列的配对,文字的拼接等领域,接下来我们在第二阶段将详细的讨论会因为分组而留下一些孤立的片段。第三阶段我们将会减少因片段过长,分组中未能产生交集导致的片段缺失,数目减少的情况。第四阶段我们将最优化模型,突破前三阶段的固定希望片段,而是考虑动态的希望片段,与文本进行匹配。
问题
众所周知,语言是我们人类沟通交流的桥梁,不仅如此,语言还可以帮助我们处理很多生活中的问题,这便是语言的功能性。近来,我们发现了一种未知的语言,目前只知道其文字是由 20个字母构成。同时我们已经获取了许多段由该语言写成的文本,但每段文本只是由字母组成的序列,因为没有标点符号和空格,所以无法让我们理解其规律及含义。因此,我们希望对这种语言展开研究,我们现在有一种思路是设法在不同段文本中搜索共同出现的字母序列的片段。语言学家猜测:如果有的序列片段在每段文本中都会出现,这些片段就很可能具备某种固定的含义 (类似词汇或词根),可以以此入手进行进一步的研究。由此可见,研究此语言具有有开拓性意义!
问题分析
问题研究及初结果分析
由以上问题,我们根据思路进行了实际实验,在文本的获取过程中,由于我们记录技术的限制,可能有一些位置出现了记录错误。因此我们对初始结果进行分析,可能的错误分为如下三种:
- 删失错误:丢失了某个字母;
- 插入错误:新增了原本不存在的字母;
- 替换错误:某个字母被篡改成了其他的字母。
BF算法
Int BF(SString S, SString T,int pos)
{
i=pos,j=1;
while(i<=S.length && j<=T.length)
{
if(S.ch[i]==T.ch[j] || S.ch[i]-T.ch<=4)
{
++i,++j;
}
else
{
i=i-j+2;j=1;
}
}
If(j>T.length)
{
return i-T.length;
}
else
{
return 0;
}
}
程序如下:
#include<iostream>
#include<fstream>
#include<string.h>
using namespace std;
typedef struct{
char ch[600]; //若是非空串,则按串长分配存储区,否则ch为NULL
int len; //串长度
}HString;
int Index_BF(HString S,HString T,int pos)
{//返回模式T在主串S中第pos个字符开始第一次出现的位置。若不存在,则返回值为0
//其中,T非空,1≤pos≤StrLength(S)
int i,j;
i=pos; j=1;
while(i<=S.len&&j<=T.len)
{
if(S.ch[i]==T.ch[j]){++i;++j;} //继续比较后继字符
else{++j;} //指针后退重新开始匹配
}
if(j>T.len && (T.len-1)-i<=0) return 1;
else return 0;
}
void Virus_detection()
{
int num,m,flag,i,j; char Vir[600];
HString Virus,Person,temp;
ifstream inFile("外星语检测输入数据.txt");
ofstream outFile("外星语检测输出结果.txt");
inFile>>num;//读取待检测的任务数
while(num--) //依次检测每个希望找到的序列片段和每段文本中的目标序列是否匹配
{
inFile>>Virus.ch+1;//读取希望找到的序列
inFile>>Person.ch+1;//读取目标序列
strcpy(Vir,Virus.ch);
Virus.len=strlen(Virus.ch)-1;
Person.len=strlen(Person.ch)-1;
flag=0;//用来标识是否匹配,初始为0,匹配后为非0
m=Virus.len;
for(i=m+1,j=1;j<=m;j++) Virus.ch[i++]=Virus.ch[j];
//因序列为环状,故将片段的长度扩大2倍
//即可线性取到所有长度为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.len=strlen(temp.ch)-1;
flag=Index_BF(Person,temp,1); //模式匹配
if(flag) break; //匹配即可退出循环
}//for
if(flag)
outFile<<Vir+1<<" "<<Person.ch+1<<" "<<"YES"<<endl;
else
outFile<<Vir+1<<" "<<Person.ch+1<<" "<<"NO"<<endl;
}//while
}
int main()
{
Virus_detection();
return 0;
}