@TOC)
实践内容
文本文件单词的检索与计数
- 任务需求
- 建立一个文本文件,统计给定单词在文本文件中出现的总次数及位置
- 需求分析
- 文本文件中每个单词不包含空格且不跨行,单词由字符序列构成且区分大小写,统计给定单词在文本 文件中出现的总次数,检索输出的某个单词出现在文本中的行号、在该行中出现的位置
- 设计数据量大的文本,进行子串的查询处理,分析算法运行的时间效率,对所有输出的匹配位置结果 进行验证,以证明算法设计和实现的正确性
- 用朴素模式匹配算法或KMP算法实现字符串定位
- 可正确读取,保存文本
开发环境
实现语言:Java
开发平台:IntelliJ IDEA
算法分析
(1)朴素模式匹配算法
用模板中的每个字符去与正文中的字符一一比较。比较成功返回1;比较失败,正文的下标向后移动一位,直到比较成功。如若正文的剩余字符的长度小于模板的长度还未匹配成功,则返回-1。
代码示例:
nt index(seqstring p,seqstring t) {
int i = 0;
int j;
int success = 0;
while((i<=p.length - t.length) && (!success)) {
j = 0;
success = 1;
while((j < p.length) && success) {
if(p.str[j] != t.str[i + j])
success = 0;
else
j ++;
}
i ++;
}
if(success)
return (i - 1);
else
return -1;
}
(2)KMP模式匹配算法
大致是因为暴力匹配浪费大量资源比如 sssssssss和ssssb直到最后一个才发现不对,若用暴力匹配法便会一直不断的回溯尝试。若采用KMP模式匹配则可以根据得到的ssss串来去避免。
比如,在简单的一次匹配失败后,我们会想将模式串尽量的右移和主串进行匹配。右移的距离在KMP算法中是如此计算的:在已经匹配的模式串子串中,找出最长的相同的前缀和后缀,然后移动使它们重叠
在第一次匹配过程中
T: a b a c a a b a c a b a c a b a a b b
W: a b a c a b
在T[5]与W[5]出现了不匹配,而T[0]T[4]是匹配的,现在T[0]T[4]就是上文中说的已经匹配的模式串子串,现在移动找出最长的相同的前缀和后缀并使他们重叠:
T: a b a c aa b a c a b a c a b a a b b
W: a b a c a b
然后在从上次匹配失败的地方进行匹配,这样就减少了匹配次数,增加了效率
代码示例、
void Getnext(int next[],String t)
{
int j=0,k=-1;
next[0]=-1;
while(j<t.length-1)
{
if(k == -1 || t[j] == t[k])
{
j++;k++;
if(t[j]==t[k])
next[j] = next[k];
else
next[j] = k;
}
else k = next[k];
}
}
int KMP(String s,String t)
{
int next[MaxSize],i=0;j=0;
Getnext(t,next);
while(i<s.length&&j<t.length)
{
if(j==-1 || s[i]==t[j])
{
i++;
j++;
}
else j=next[j];
}
if(j>=t.length)
return (i-t.length);
else
return (-1);
}
主要是Getnext方法去直到移动的距离。