[每天默写一个算法]KMP

作业要求:默写String的KMP算法。

KMP是经典的字符串匹配算法。复杂度为O(n+m)

     public static class StringKMP
{
/// <summary>
/// This indicates that no pattern found from source.
/// </summary>
public const int KMPNoMatch = -;
/// <summary>
/// Special value of next[] array, which means i should be increased by 1 and j sould be reset to 0.
/// </summary>
public const int FirstBlood = -;
/// <summary>
/// Find first match for specified pattern in the source.
/// </summary>
/// <param name="source"></param>
/// <param name="pattern"></param>
/// <returns></returns>
public static int KMP(this String source, String pattern)
{
if (string.IsNullOrEmpty(source) || string.IsNullOrEmpty(pattern))
{ return KMPNoMatch; }
var i = ; var j = ; var result = KMPNoMatch;
var nextVal = GetNextVal(pattern); while (i < source.Length && j < pattern.Length)
{
if (j == FirstBlood)
{// source[i] does NOT equal with pattern[0], so i should be increased by 1 and j should be reset to 0.
i++; j = ;
}
else if (source[i].Equals(pattern[j]))
{
i++; j++;
}
else
{// Get next j that should be compared with.
j = nextVal[j];
}
} if (j >= pattern.Length)// Match succeeded.
{ result = i - pattern.Length; } return result;
}
/// <summary>
/// nextVal[j]: source[i] should compare with pattern[ nextVal[j] ] in next loop
/// <para>if source[i] does NOT equal with pattern[j].</para>
/// <para>Specially, if source[i] does NOT equal with pattern[0], then i should be increased by 1</para>
/// <para>and j should be reset to 0.</para>
/// <para>So we should always set nextVal[0] = FirstBlood.</para>
/// </summary>
/// <param name="pattern"></param>
/// <returns></returns>
private static int[] GetNextVal(String pattern)
{
var j = ; var k = -;
var nextVal = new int[pattern.Length]; nextVal[] = FirstBlood; while (j < pattern.Length - )
{
if ((k == -) || (pattern[j].Equals(pattern[k])))
{
j++; k++;
if (!(pattern[j].Equals(pattern[k])))
{ nextVal[j] = k; }
else
{ nextVal[j] = nextVal[k]; }
}
else
{ k = nextVal[k]; }
} return nextVal;
}
}

字符串能匹配,其他类型的串(数组Array和泛型数组IList<T>)也就可以匹配。

 using System;
using System.Collections.Generic;
using System.Linq;
using System.Text; namespace System
{
public static class StringKMP
{
/// <summary>
/// This indicates that no pattern found from source.
/// </summary>
public const int KMPNoMatch = -;
/// <summary>
/// Special value of next[] array, which means i should be increased by 1 and j sould be reset to 0.
/// </summary>
private const int FirstBlood = -;
/// <summary>
/// Find first match for specified pattern in the source.
/// </summary>
/// <param name="source"></param>
/// <param name="pattern"></param>
/// <returns></returns>
public static int KMP(this String source, String pattern)
{
if (string.IsNullOrEmpty(source) || string.IsNullOrEmpty(pattern))
{ return KMPNoMatch; }
var i = ; var j = ; var result = KMPNoMatch;
var nextVal = GetNextVal(pattern); while (i < source.Length && j < pattern.Length)
{
if (j == FirstBlood)
{// source[i] does NOT equal with pattern[0], so i should be increased by 1 and j should be reset to 0.
i++; j = ;
}
else if (source[i].Equals(pattern[j]))
{
i++; j++;
}
else
{// Get next j that should be compared with.
j = nextVal[j];
}
} if (j >= pattern.Length)// Match succeeded.
{ result = i - pattern.Length; } return result;
}
/// <summary>
/// nextVal[j]: source[i] should compare with pattern[ nextVal[j] ] in next loop
/// <para>if source[i] does NOT equal with pattern[j].</para>
/// <para>Specially, if source[i] does NOT equal with pattern[0], then i should be increased by 1</para>
/// <para>and j should be reset to 0.</para>
/// <para>So we should always set nextVal[0] = FirstBlood.</para>
/// </summary>
/// <param name="pattern"></param>
/// <returns></returns>
private static int[] GetNextVal(String pattern)
{
var j = ; var k = -;
var nextVal = new int[pattern.Length]; nextVal[] = FirstBlood; while (j < pattern.Length - )
{
if ((k == -) || (pattern[j].Equals(pattern[k])))
{
j++; k++;
if (!(pattern[j].Equals(pattern[k])))
{ nextVal[j] = k; }
else
{ nextVal[j] = nextVal[k]; }
}
else
{ k = nextVal[k]; }
} return nextVal;
}
} public static class ArrayKMP
{
/// <summary>
/// This indicates that no pattern found from source.
/// </summary>
public const int KMPNoMatch = -;
/// <summary>
/// Special value of next[] array, which means i should be increased by 1 and j sould be reset to 0.
/// </summary>
private const int FirstBlood = -;
/// <summary>
/// Find first match for specified pattern in the source.
/// </summary>
/// <param name="source"></param>
/// <param name="pattern"></param>
/// <returns></returns>
public static int KMP(this Array source, Array pattern)
{
if (source == null || pattern == null || source.Length == || pattern.Length == )
{ return KMPNoMatch; }
var i = ; var j = ; var result = KMPNoMatch;
var nextVal = GetNextVal(pattern); while (i < source.Length && j < pattern.Length)
{
if (j == FirstBlood)
{// source[i] does NOT equal with pattern[0], so i should be increased by 1 and j should be reset to 0.
i++; j = ;
}
else if (source.GetValue(i).Equals(pattern.GetValue(j)))
{
i++; j++;
}
else
{// Get next j that should be compared with.
j = nextVal[j];
}
} if (j >= pattern.Length)// Match succeeded.
{ result = i - pattern.Length; } return result;
}
/// <summary>
/// nextVal[j]: source[i] should compare with pattern[ nextVal[j] ] in next loop
/// <para>if source[i] does NOT equal with pattern[j].</para>
/// <para>Specially, if source[i] does NOT equal with pattern[0], then i should be increased by 1</para>
/// <para>and j should be reset to 0.</para>
/// <para>So we should always set nextVal[0] = FirstBlood.</para>
/// </summary>
/// <param name="pattern"></param>
/// <returns></returns>
private static int[] GetNextVal(Array pattern)
{
var j = ; var k = -;
var nextVal = new int[pattern.Length]; nextVal[] = FirstBlood; while (j < pattern.Length - )
{
if ((k == -) || (pattern.GetValue(j).Equals(pattern.GetValue(k))))
{
j++; k++;
if (!(pattern.GetValue(j).Equals(pattern.GetValue(k))))
{ nextVal[j] = k; }
else
{ nextVal[j] = nextVal[k]; }
}
else
{ k = nextVal[k]; }
} return nextVal;
}
} public static class IListKMP
{
sealed class DefaultComparer<T> : IComparer<T>
{
private static readonly DefaultComparer<T> instance = new DefaultComparer<T>(); public static DefaultComparer<T> Instance
{
get { return DefaultComparer<T>.instance; }
} int IComparer<T>.Compare(T x, T y)
{
if (x.Equals(y)) { return ; }
else { return ; }
}
} /// <summary>
/// This indicates that no pattern found from source.
/// </summary>
public const int KMPNoMatch = -;
/// <summary>
/// Special value of next[] array, which means i should be increased by 1 and j sould be reset to 0.
/// </summary>
private const int FirstBlood = -;
/// <summary>
/// Find first match for specified pattern in the source.
/// </summary>
/// <param name="source"></param>
/// <param name="pattern"></param>
/// <param name="comparer"></param>
/// <returns></returns>
public static int KMP<T>(this IList<T> source, IList<T> pattern, IComparer<T> comparer = null)
{
if (source == null || pattern == null || source.Count == || pattern.Count == )
{ return KMPNoMatch; } if (comparer == null) { comparer = DefaultComparer<T>.Instance; } var i = ; var j = ; var result = KMPNoMatch;
var nextVal = GetNextVal(pattern, comparer); while (i < source.Count && j < pattern.Count)
{
if (j == FirstBlood)
{// source[i] does NOT equal with pattern[0], so i should be increased by 1 and j should be reset to 0.
i++; j = ;
}
else if (comparer.Compare(source[i], pattern[j]) == ) //(source[i].Equals(pattern[j]))
{
i++; j++;
}
else
{// Get next j that should be compared with.
j = nextVal[j];
}
} if (j >= pattern.Count)// Match succeeded.
{ result = i - pattern.Count; } return result;
} /// <summary>
/// nextVal[j]: source[i] should compare with pattern[ nextVal[j] ] in next loop
/// <para>if source[i] does NOT equal with pattern[j].</para>
/// <para>Specially, if source[i] does NOT equal with pattern[0], then i should be increased by 1</para>
/// <para>and j should be reset to 0.</para>
/// <para>So we should always set nextVal[0] = FirstBlood.</para>
/// </summary>
/// <param name="pattern"></param>
/// <returns></returns>
private static int[] GetNextVal<T>(IList<T> pattern, IComparer<T> comparer)
{
var j = ; var k = -;
var nextVal = new int[pattern.Count]; nextVal[] = FirstBlood; while (j < pattern.Count - )
{
if ((k == -) || (comparer.Compare(pattern[j], pattern[k]) == ))
{
j++; k++;
if (!(comparer.Compare(pattern[j], pattern[k]) == ))
{ nextVal[j] = k; }
else
{ nextVal[j] = nextVal[k]; }
}
else
{ k = nextVal[k]; }
} return nextVal;
} } }

[每天默写一个算法]KMP的更多相关文章

  1. 数据结构与算法--KMP算法查找子字符串

    数据结构与算法--KMP算法查找子字符串 部分内容和图片来自这三篇文章: 这篇文章.这篇文章.还有这篇他们写得非常棒.结合他们的解释和自己的理解,完成了本文. 上一节介绍了暴力法查找子字符串,同时也发 ...

  2. 经典算法 KMP算法详解

    内容: 1.问题引入 2.暴力求解方法 3.优化方法 4.KMP算法 1.问题引入 原始问题: 对于一个字符串 str (长度为N)和另一个字符串 match (长度为M),如果 match 是 st ...

  3. 笔记-算法-KMP算法

    笔记-算法-KMP算法 1.      KMP算法 KMP算法是一种改进的字符串匹配算法,KMP算法的关键是利用匹配失败后的信息,尽量减少模式串与主串的匹配次数以达到快速匹配的目的.具体实现就是实现一 ...

  4. 值得花费一周研究的算法 -- KMP算法(indexOf)

    KMP算法是由三个科学家(kmp分别是他们名字的首字母)创造出来的一种字符串匹配算法. 所解决的问题: 求文本字符串text内寻找第一次出现字符串s的下标,若未出现返回-1. 例如 text : &q ...

  5. 介绍对称加密的另一个算法——PBE

    除了DES,我们还知道有DESede(TripleDES,就是3DES).AES.Blowfish.RC2.RC4(ARCFOUR)等多种对称加密方式,其实现方式大同小异,这里介绍对称加密的另一个算法 ...

  6. 推荐一个算法编程学习中文社区-51NOD【算法分级,支持多语言,可在线编译】

    最近偶尔发现一个算法编程学习的论坛,刚开始有点好奇,也只是注册了一下.最近有时间好好研究了一下,的确非常赞,所以推荐给大家.功能和介绍看下面介绍吧.首页的标题很给劲,很纯粹的Coding社区....虽 ...

  7. cc150:实现一个算法来删除单链表中间的一个结点,仅仅给出指向那个结点的指针

    实现一个算法来删除单链表中间的一个结点,仅仅给出指向那个结点的指针. 样例: 输入:指向链表a->b->c->d->e中结点c的指针 结果:不须要返回什么,得到一个新链表:a- ...

  8. 设单链表中存放n个字符,试设计一个算法,使用栈推断该字符串是否中心对称

    转载请注明出处:http://blog.csdn.net/u012860063 问题:设单链表中存放n个字符.试设计一个算法,使用栈推断该字符串是否中心对称,如xyzzyx即为中心对称字符串. 代码例 ...

  9. python学习:设计一个算法将缺失的数字找出来。

    算法题   已知整型数值 a[99], 包含的所有99个元素都是从1-100中随机取值,并且这99个数两两互不相等,也就是说从1到100这100个数字有99个在数值内,有一个缺失.请设计一个算法将缺失 ...

随机推荐

  1. WIN2003使用IP安全策略只允许指定IP远程桌面连接

    一,新建IP安全策略 WIN+R打开运行对话框,输入gpedit.msc进入组策略编辑器. 依次打开“本地计算机”策略--计算机配置--Windows设置--安全设置--IP安全策略,在 本地计算机上 ...

  2. android系统启动

    首页 资讯 精华 论坛 问答 博客 专栏 群组 更多 ▼ 您还未登录 ! 登录 注册 Ant space   博客 微博 相册 收藏 留言 关于我     android启动过程再研   Androi ...

  3. android 常见面试题以及答案

    http://blog.csdn.net/bobo1808/article/details/6783344 1.    请描述下Activity的生命周期.2.    如果后台的Activity由于某 ...

  4. UI基础之UIButton相关

    UIButton *btn = [UIButton buttonWithType:UIButtonTypeCustom]; 1.按钮透明效果 btn.alpha = 0.8; 2.按钮圆角处理 btn ...

  5. Java中实现PHP中的urlencode与rawurlencode

    php手册中对urlencode这样说明 在java中 URLEncoder做了这样注释 也就是说java中对星号"*"是不进行编码的 也就是说URLEncoder之后还是&quo ...

  6. JavaScript-事件坐标

    事件坐标: 1.参照屏幕左上角e.screenX,e.screenY 2.参照文档显示区左上角:e.clientX||e.x , e.clientY||e.y 3.参照所在父元素的左上角:e.offs ...

  7. spring mvc 使用ehcache

    一.需要导入的jar包 1.ehcache.jar 2.ehcache-spring-annotations-1.2.0.jar 3.guava-r09.jar 4.slf4j-api-1.6.6.j ...

  8. php压缩文件

    $filename = './qrcode.zip'; // 最终生成的文件名(含路径) //生成文件 $zip = new ZipArchive (); // 使用本类,linux需开启zlib,w ...

  9. mac OS X 配置Python+Web.py+MySQLdb环境

    MAC默认支持Python 2.7所以不用安装. 1.安装pip sudo easy_install pip 2.安装Web.py sudo pip install Web.py 3.安装MySQLd ...

  10. android 的数学公式图片转换

    在应用中的数学公式是不能直接以文本显示和输入的,包括在一些学习类网站上看到的公式,他们都是以gif图片的形式展示出来的.而怎么样生成各种各样的gif图片形式的数学公式呢,此处未作深入研究,我所知道的是 ...