您的位置:首页 > 编程语言 > Java开发

Kmp字符串匹配算法

2013-09-28 23:02 253 查看
上一篇文章,已经讲过了Horspool匹配算法,确实Horspool是一种优秀的算法,它实现了θ(n)的一般效率对文本串的查找,但也有一种算法——Kmp,它也能实现这种效率

先看一下该算法执行的移动过程(即模式串的next数组的值)
先声说明:本人认为该算法在移动值的求法比Horspool不好理解,对于初次接触的人理解会有点难度,不过给予点耐心,还是可以看得懂的
另外下面的 i ,j 变量在下面的函数shiftTable中,请结合理解
未改进:

下标01234567
模式串abaabcac
next-10011201
归纳:
其实next的求法就是:1)如果匹配跳动变量j在下表为0时,遍历变量i和匹配跳动变量j都+1,且next[i] = j;
                                    2)匹配跳动变量j 和遍历变量 i 变量所对应字符一样,便利变量i和匹配跳动变量j都+1,且next[i] = j;
                                    3)以上两种情况不满足,则j = next[j],继续和遍历变量i比较

改进:

下标01234567
模式串abaabcac
next-10-1102-11
       
归纳:其实改进后的算法和为改进相差不是很多,不过时间效率就提高了,就是在第2种情况下,加上:如果遍历变量i和匹配跳动变量j在+1之后在比较,如果两者 = ,那说明i位置不符合时,j位置也不符合,所以只能next[i] = next[j],如下标为2的a next值是-1

先看一下,未改进的shiftTable函数

//求模式串的next数组
public int[] shiftTable(char[] m)
{
int[] next = new int[m.length];
int mLen = m.length;
//第一个字符next值
next[0] = -1;

//j在遍历比较过程中会跳动
int j = -1;

//i为遍历模式串的变量
for(int i=0; i<mLen-1;)
if(j == -1 || m[i] == m[j])
{
i++;
j++;

next[i] = j;
}
else j = next[j];

return next;
}


改进后的shiftTable函数

/**
* 求模式串的next数组
* @param m
*            模式串
* @return
*/
public static int[] shiftTable(char[] m)
{
int mLen = m.length;
int[] next = new int[mLen];

// 第一个字符next值
next[0] = -1;

// j在遍历比较过程中会跳动
int j = -1;

// i为遍历模式串的变量
for (int i = 0; i < mLen - 1;)
if (j == -1 || m[i] == m[j])
{
i++;
j++;

if (m[i] == m[j])
next[i] = next[j];
else
next[i] = j;
}
else
j = next[j];

return next;
}


在看一下匹配函数

/**
* 匹配函数,其中p为模式串,m为模式串长度,t为文本串,n为文本串长度,next为next数组
*
* @param m
*            模式串
* @param t
*            文本串
* @return
*/
public static int kmp(char[] m, char[] t)
{
int[] next = shiftTable(m);
int mLen = m.length;
int tLen = t.length;

// 遍历文本串n的变量
int i = 0;

// 表示模式串将验证位置的变量
int j = 0;

while (i < tLen && j < mLen)
{
// 如果匹配或者j为-1,匹配下一个字符
if (j == -1 || t[i] == m[j])
{
i++;
j++;
}
else
{
j = next[j];
}
}

if (j == mLen)
return i - j;
else
return -1;

}


验证:

// args[0]为模式串,args[1]为文本串
public static void main(String args[])
{

System.out.println(kmp("abaabcac".toCharArray(),
"asdfaddsdabaabcacsdws".toCharArray()));
}


输入:

args[0]: abaabcac
args[a]: asdfaddsdabaabcacsdws

输出: 9
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  kmp 移动 算法 遍历 Java