字符串匹配算法研究(一)
2008-02-29 10:10
405 查看
字符串匹配算法研究(一)
上星期拜读了2004年中国IOI集训队中朱泽园(当时就读南京市外国语学校)的一篇论文《多串匹配算法及启示》,并将其中的部分算法在理解的基础上用C++和Java做了实现。现将本人的理解与代码帖出,请读者不吝赐教。首先我把该算法要解决的问题重新描述一下:即给定m个长度不等的模式串S1,S2,...,Sm以及一篇长度为n的正文T,求min({s|整数s∈[0,n-1],且存在整数a∈[1,m],使得T.subString(s,Sa.length-1)=Sa})。例如,当正文T=abcdefgh,S1=cdefg,S2=efg,则s=2。(因为S1出现在T下标为2的子串处,S2出现在T下标为4的子串处,min(2,4)=2)。
对于解决该问题的实际意义,论文作者已表述得十分清楚:“含逻辑关键字的搜索引擎是这个问题的实际应用。医学家们在DNA序列中,搜索可能为变异的几种模式,也是这类问题的典型。因此用有效算法解决该问题
能大大提高各行业的工作效率。”
对于如何解决该问题,作者首先给出了最容易相到的枚举法及其优化。由于该想法太过简单,只要稍具编程基础的人都能想到因此我就不再讨论了。总而言之,用枚举法解决该问题的时间复杂度为O(n*sum({Si.length|i=1,2,...,n}))。而对于问题的规模而言,明显枚举法是力不从心的。
为了有效地解决该问题,作者先将问题简化。即当模式串只有一个时,多串匹配问题就变成了单串匹配问题。对于单串匹配作者发现了一现成的算法:kmp(Knuth-Morris-Pratt)算法。kmp算法的功能如下:
输入:模式串P(长度为m),正文T(长度为n)
输出:集合{s|整数s∈[1,m+n-1]且T.subString(s,m-1)=P}
kmp算法的主体思想是先给出模式串的前缀函数(定义:Pi(j)=max{j|P.subString(0,j)=P.subString(i-j,i),j∈[0,i]}),对模式串进行预处理,之后在拿原文和模式串比较时,可根据模式串的前缀函数来移位,减少不必要的比较次数。现给出代码:
/** *//**
*
* @author liuxy
* 用Kmp算法解决单串匹配问题
*/
public class Kmp ...{
/** *//**
* 对模式串p进行预处理,计算其前缀函数,算法如下:
* k<-0
* pi[0]<-0
* For i<-1 to p.length do
* while k>0 and p[k]!=p[i] Do k<-pi[k-1];
* If P[k]=p[i] Then k<-k+1
* pi[i]<-k
* End For
* 算法时间复杂度为O(p.length)
*
* @param p
* @return int[]
*/
public static int[] kmpInit(String p)...{
int[] pi = new int[p.length()];
pi[0] = 0;
int k = 0;
for(int i = 1; i < p.length(); ++i)...{
pi[i] = 0;
while(k > 0 && p.charAt(k) != p.charAt(i))
k = pi[k-1];
if(p.charAt(k) == p.charAt(i))++k;
pi[i] = k;
}
return pi;
}
/**
*//**
* kmp主算法,算法如下:
* run kmpInit(p)
* q<-0
* For i<-0 to text.length Do
* while q>0 and p[q]!=text[i] Do q<-pi[q-1]
* If p[q]=text[i] Do q<-q+1
* if q=m Then
* write "在i-m+1处出现模式串"
* q<-pi[q-1]
* End if
* End For
* 算法时间复杂度为O(text.length+p.length)
*
* @param text
* @param p
*/
public static void kmp(String text, String p)...{
int n = text.length(), m = p.length();
int q = 0;
int[] pi = kmpInit(p);
for(int i = 0; i < n; ++i)...{
while(q > 0 && p.charAt(q) != text.charAt(i))q = pi[q-1];
if(p.charAt(q) == text.charAt(i))++q;
if(q == m)...{
System.out.println(i-m+1);
q = pi[q-1];
}
}
}
}
相关文章推荐
- 字符串匹配算法研究
- 【总结】关于字符串匹配算法研究
- 关于字符串匹配算法研究 http://www.cnblogs.com/Su-30MKK/archive/2012/09/17/2688122.html
- 一个自己研究出来的字符串匹配算法-k子串算法
- 字符串匹配算法研究(二)
- 字符串匹配自动机的算法原理
- PHP 字符串匹配算法 Sunday算法
- 【算法】一种字符串匹配算法:z-algorithm
- 【字符串匹配】——KMP(看毛片算法)——深入讲解next数组的求解
- 数据集成字符串匹配算法:EditDIstance,NeedlemanWunch,Soundex,Jaccard
- 多模字符串匹配算法原理及Java实现代码
- 字符串匹配算法总结
- 字符串匹配算法,包含通配符"*"、"?"的匹配
- 算法学习之字符串匹配 KMP 算法(一)(原理介绍)
- 字符串匹配之朴素算法和通配符扩展
- 基本算法之字符串匹配算法Sunday
- 子字符串substring 问题 - KMP 字符串匹配算法备忘录
- 字符串匹配算法——利用有限自动机进行匹配
- 字符串匹配算法 最长前缀后缀法