[每天默写一个算法]KMP
[每天默写一个算法]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的更多相关文章
- 数据结构与算法--KMP算法查找子字符串
数据结构与算法--KMP算法查找子字符串 部分内容和图片来自这三篇文章: 这篇文章.这篇文章.还有这篇他们写得非常棒.结合他们的解释和自己的理解,完成了本文. 上一节介绍了暴力法查找子字符串,同时也发 ...
- 经典算法 KMP算法详解
内容: 1.问题引入 2.暴力求解方法 3.优化方法 4.KMP算法 1.问题引入 原始问题: 对于一个字符串 str (长度为N)和另一个字符串 match (长度为M),如果 match 是 st ...
- 笔记-算法-KMP算法
笔记-算法-KMP算法 1. KMP算法 KMP算法是一种改进的字符串匹配算法,KMP算法的关键是利用匹配失败后的信息,尽量减少模式串与主串的匹配次数以达到快速匹配的目的.具体实现就是实现一 ...
- 值得花费一周研究的算法 -- KMP算法(indexOf)
KMP算法是由三个科学家(kmp分别是他们名字的首字母)创造出来的一种字符串匹配算法. 所解决的问题: 求文本字符串text内寻找第一次出现字符串s的下标,若未出现返回-1. 例如 text : &q ...
- 介绍对称加密的另一个算法——PBE
除了DES,我们还知道有DESede(TripleDES,就是3DES).AES.Blowfish.RC2.RC4(ARCFOUR)等多种对称加密方式,其实现方式大同小异,这里介绍对称加密的另一个算法 ...
- 推荐一个算法编程学习中文社区-51NOD【算法分级,支持多语言,可在线编译】
最近偶尔发现一个算法编程学习的论坛,刚开始有点好奇,也只是注册了一下.最近有时间好好研究了一下,的确非常赞,所以推荐给大家.功能和介绍看下面介绍吧.首页的标题很给劲,很纯粹的Coding社区....虽 ...
- cc150:实现一个算法来删除单链表中间的一个结点,仅仅给出指向那个结点的指针
实现一个算法来删除单链表中间的一个结点,仅仅给出指向那个结点的指针. 样例: 输入:指向链表a->b->c->d->e中结点c的指针 结果:不须要返回什么,得到一个新链表:a- ...
- 设单链表中存放n个字符,试设计一个算法,使用栈推断该字符串是否中心对称
转载请注明出处:http://blog.csdn.net/u012860063 问题:设单链表中存放n个字符.试设计一个算法,使用栈推断该字符串是否中心对称,如xyzzyx即为中心对称字符串. 代码例 ...
- python学习:设计一个算法将缺失的数字找出来。
算法题 已知整型数值 a[99], 包含的所有99个元素都是从1-100中随机取值,并且这99个数两两互不相等,也就是说从1到100这100个数字有99个在数值内,有一个缺失.请设计一个算法将缺失 ...
随机推荐
- 用servlet和jsp做探索数据库
1.建一个web文件,在里面分三层,分别是实体层:DAO层,DAO层里面包含BaseDAO(数据访问层)和DAO层:还有一个servlet层,处理数据逻辑层! 一.实体层,建立两个实体,一个membe ...
- 修改Linux可显示的行数
在/boot/grub/menu.lst中,找到kernel开头的那一行,在后面加上参数vga=791 下面是vga可以取的值 # +----------------------------- ...
- css大小单位px em rem的转换和详解
css大小单位px em rem的转换和详解 PX特点1. IE无法调整那些使用px作为单位的字体大小:2. 国外的大部分网站能够调整的原因在于其使用了em或rem作为字体单位:3. Firefox能 ...
- HDU 1575
Tr A Time Limit: 1000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total Submis ...
- 《photon中配置lite的相关问题》
前几天在学习photon的时候发现了一个问题: 无论如何都找不到Lite文件夹,我是一个新手这也是写给那些新上手的朋友: 首先下载SDK以后配置完成后无论如何都找不到Lite文件夹和相关的Lite.d ...
- CSS clear清除浮动
1.CSS中的clear有四个参数: none:允许两边都可以浮动. left:不允许左边有浮动. right:不允许右边有浮动. both(默认):不允许有浮动. 2.一开始在CSS中clear浮动 ...
- MyBatis Generator 详解 【转来纯为备忘】
版权声明:版权归博主所有,转载请带上本文链接!联系方式:abel533@gmail.com 目录(?)[+] MyBatis Generator中文文档 运行MyBatis Generator X ...
- 使用joi来验证数据模型
我们用nodejs实现一些功能时,往往需要对用户输入的数据进行验证.然而,验证是一件麻烦的事情,很有可能你需要验证数据类型,长度,特定规则等等,在前端做表单验证时,我们常用的做法是使用正则,正则表达式 ...
- ArcGIS百米网格自动生成
最近需要用百米网格进行空间叠加分析,首先得自动生成百米网格数据.经过查找,发现ARCgis可以自动生成网格.方法如下 2.创建格网(Creat Fishnet).需要用到ArcGIS的ArcToolb ...
- Centos配置查看
Reference: [1] http://www.centoscn.com/CentOS/help/2013/0928/1743.html [2] http://www.cnblogs.com/hi ...