hihocoder 第三周
2015-08-18 11:07
155 查看
提示二:NEXT数组的使用
“那么,为了能够充分理解NEXT数组,我们再来回顾一下如何使用NEXT数组~"小Hi摆出一副老师的样子,说道。”首先我们来给出NEXT数组的数学定义~“NEXT[0] = -1NEXT[i] = max{ 0<=k< i | str.substring(1, k) == str.substring(i - k +1 , i) } 其中str.substring(i, j)表示str从位置i到位置j的子串,如果i>j则,substring为空
”那么我们对之前例子中的模式串进行求解,可以得到这样的NEXT数组。“小Hi在纸上写了又写,画了又画。
模式串: | b a b a b b |
NEXT: | 0 0 1 2 3 1 |
”好的!小Hi老师好棒!“小Ho在一旁煽风点火道。
原串(p=5): | babab | abcbababababb |
模式串(q=5): | babab | b |
原串(p=5): | babab | abcbababababb |
模式串(q=3): | bab | abb |
原串(p=7): | bababab | cbababababb |
模式串(q=5): | babab | b |
原串(p=7): | bababab | cbababababb |
模式串(q=3): | bab | abb |
原串(p=7): | bababab | cbababababb |
模式串(q=1): | b | ababb |
原串(p=7): | bababab | cbababababb |
模式串(q=0): | | bababb |
原串(p=7): | bababab | cbababababb |
模式串(q=-1): | | bababb |
“这样一说,我就大致能够理解NEXT数组是怎么用来求解模式匹配问题的了,但是它是如何求的呢?一般的方法不是要O(模式串长度的立方)的么?”小Ho问道。
“这就是我接下来要和你说的啦!”小Hi笑道:“但是让我先喝口水!”
提示三:如何求解NEXT数组
“首先我们不想如何求整个NEXT数组,而是假设我们已经知道了之前例子中模式串的NEXT[1..4],来求NEXT[5]如何?”小Hi建议道。“好的!这样我们就只需要平方级的算法就可以算出它的值了!”小Ho高兴道。
“有点追求好不好!”小Hi深深的吸了一口气:“你这样和之前的解法有什么不同么!”
“似乎没有。。那你说怎么算吧!我反正脑子已经成浆糊了。”小Ho郁闷道。
“我们把par.substring(1, 5)当做新的原串ori_new,然后把par.substring(1, 4)当做新的模式串par,会如何?”小Hi微微一笑。
“会。。我来试试!"小Ho接过小Hi手中的纸笔,便开始演算:“首先就直接匹配到了p=4, q=4的情况,这时候严格来说已经算匹配完成了,但是肯定不是就这么结束的,此时par_new[q +1]因为是空字符,所以肯定和ori_new[p+1]匹配不上。于是令q = NEXT[q]”
原串(p=4): | baba | b |
模式串(q=4): | baba | |
原串(p=4): | baba | b |
模式串(q=2): | ba | b |
”没错,就是这样!那你想想现在如何求NEXT[6]。“小Hi继续引导小Ho。
”首先我们没有必要重新从头开始匹配,直接在原串和模式串的后面加上第6个字符就可以了。“小Ho分析道。
原串(p=5): | babab | b |
模式串(q=3): | bab | abb |
原串(p=5): | babab | b |
模式串(q=1): | b | ababb |
原串(p=5): | babab | b |
模式串(q=0): | | bababb |
”那你要不要赶紧去写一下代码,KMP算法的代码可是可以写的很短很巧妙的哦!~“小Hi建议道。
”好!“
/* * next[]的含义: x[i-next[i]...i-1]=x[0...next[i]-1] * next[i]为满足x[i-z...i-1]=x[0...z-1]的最大z值(就是x的自身匹配) */ void kmp_pre(char x[],int m,int next[]) { int i,j; j = next[0] = -1; i = 0; while(i < m) { while(-1 != j && x[i] != x[j]) j = next[j]; next[++i] = ++j; } } int next[10010]; int KMP_Count(char x[],int m,char y[],int n) {//x是模式串, y是主串 int i, j; int ans = 0; kmp_pre(x, m, next); i = j = 0; while(i < n) { while(-1 != j && y[i] != x[j]) j = next[j]; i++; j++; if(j >= m) { ans++; j = next[j]; } } return ans; }
相关文章推荐
- 去掉空格
- UI和UX的10个不同点
- HDU 4336-Card Collector(状压,概率dp)
- 风云人物——赵海平
- POJ1151--Atlantis(离散化+扫描线)
- Contains Duplicate II
- View注入框架:Butterknife简单使用
- POJ-2488-A Knight's Journey-DFS
- 软件工程师的鄙视链
- SAP 财务会计结构
- 我的模拟OC测试
- Android学习路线
- 100分程序员的8个习惯
- java - HttpRequest (get&post)
- 某搜索公司面试 待续
- Android ImageView设置图片的可见性
- SAP系统中设备管理模块的主要增强出口
- 亚马逊记AWS(Amazon Web Services)自由EC2应用
- nginx配置长连接
- Thread.setDefaultUncaughtExceptionHandler作用