其中next序列,表示子串的前后缀最大匹配长度. 例如对于字符串C[], next[i]表示子串c[0 .. i]中, 前缀与后缀的最大匹配长度.

举例如果子串是 abcuab, 其前缀是a, ab, abc, abcu, abcua, 后缀是 b, ab, uab, cuab, bcuab, 其中匹配的最大子串是ab, 长度是2.

按定义挨个计算next的值

    public static int[] getNexts(char[] tt)
{
int[] nexts = new int[tt.length];
nexts[0] = 0;
// 从1到结束, 挨个计算next
for (int i = 1; i < tt.length; i++)
{
// 在给定的子串里, 记录matched时, 最大的长度值
for (int j = 0; j < i; j++)
{
boolean matched = true;
// 使用 k, 依次比较从 0 到 j 和从 i-j 到 i的字符是否相等, 注意下标都是从小往大移动
for (int k = 0; k <= j; k++)
{
if (tt[k] != tt[i-j+k])
{
matched = false;
break;
}
} // 匹配的, 记录最大长度
if (matched)
{
int length = j + 1;
if (nexts[i] < length)
nexts[i] = length;
}
}
} return nexts;
}

改进后的方法, 在遍历中依次记录next的值, 令循环减少许多

    /**
* 只使用两个起始下标, 来计算和记录next序列
*
* @param tt
* @return
*/
public static int[] getNexts2(char[] tt)
{
int[] nexts = new int[tt.length]; nexts[0] = 0;
// 前缀起始下标
int prefix = 0;
// 后缀起始下标
int suffix = prefix + 1;
// 匹配长度
int len = 0;
while(suffix < tt.length)
{
if (tt[prefix] == tt[suffix])
{
// 如果匹配, 则记录下当前的next最大值, 并且将前缀和后缀下标都往大移动一位
prefix++;
len++;
if (nexts[suffix] < len)
nexts[suffix] = len;
}
else
{
// 如果不匹配, 则当前长度归零, 并且前缀回归起点, 而后缀依然往后走
len = 0;
prefix = 0;
}
suffix++;
} return nexts;
}

字符串搜索过程:

    public static int kmpFind(char[] ss, char[] tt)
{
// 内容串下标
int spos = 0;
// 搜索串下标
int tpos = 0; // 计算next序列
int[] nexts = getNexts2(tt);
while (spos < ss.length)
{
if (ss[spos] == tt[tpos])
{
// 匹配上后, 判断是否满足退出条件
if (tpos == tt.length - 1) return spos - tt.length + 1;
if (tpos == ss.length - 1) return -1;
// 否则继续往后匹配
spos++;
tpos++;
}
else
{
// 未匹配的情况下, 如果搜索串是第一步都未中, 则内容串下标继续移动
if (tpos == 0)
spos++;
// 否则调整搜索串下标到前一步的next值(忽略掉最大前缀)
else
tpos = nexts[tpos - 1];
}
} return -1;
}

http://jakeboxer.com/blog/2009/12/13/the-knuth-morris-pratt-algorithm-in-my-own-words/

最新文章

  1. CocoaPods被卡住:Updating local specs repositories
  2. AChartEngine方法的使用及事件汇总
  3. JSP显示不完全问题
  4. MySQL主从架构之Master-Master互为主备
  5. laravel运行url404错误
  6. phpcms 内容——&gt;评论管理 中添加 打开文章链接的 功能
  7. SQL SERVER 2008筛选时报错 无法为该请求检索数据
  8. C语言程序设计(翁恺)--第三周课件中的三个遗留点
  9. OpenSUSE 13.2安装Texlive2014+Texmaker+Lyx
  10. idea为tomcat设置虚拟地址
  11. python 列表生成式,生成器&amp;迭代器
  12. springcloud集成zookeeper,并使用configserver作为服务的配置中心
  13. poj3104 Drying(二分最大化最小值 好题)
  14. Linux环境变量PATH
  15. 微信公众号使用LocalStorage解决返回缓存问题
  16. Lintcode: Find Peak Element
  17. virtualbox+vagrant学习-4-Vagrantfile-1-简介
  18. PGM学习之七 MRF,马尔科夫随机场
  19. 【uoj#21】[UR #1]缩进优化 数学
  20. I/O复用的应用场合

热门文章

  1. mac os intellij如何快路查看一个java类的所有方法,结构
  2. iOS本地推送与远程推送
  3. 查看特定View的默认属性值
  4. 认识Activity,创建第一个android应用-Hello Word
  5. iOS手势的传递问题
  6. 直接双击启动tomcat中的startup.bat闪退原因及解决方法
  7. google不能访问的根本解决方法
  8. 示例详解:UIScrollview 与 Autolayout 的那点事
  9. Java基础知识学习(七)
  10. JavaWeb 的学习一