KMP算法的实现
今天看到了一篇关于KMP算法的讲解的文章,很难得,讲得非常清楚。分享给大家,希望对大家有帮助。http://kb.cnblogs.com/page/176818/
我自己基于这个讲解的内容作了一个实现,效果还不错,码代码的功力有限,还请大家多指正其中可以改进的地方。
using System.Collections.Generic; namespace KMPImplementation
{
/// <summary>
/// 该类用于生成KMP算法中,需要用的部分匹配表
/// </summary>
public class PartialMatchTable
{
private string data;
List<int> OffsetArray = new List<int>(); /// <summary>
/// 在构造函数中获得匹配模式,并计算产生部分匹配表
/// </summary>
/// <param name="para"></param>
public PartialMatchTable(string para)
{
data = para;
GenerateOffsetArray();
} /// <summary>
/// 计算一个字符串中,最长的相同前缀与后缀的长度
/// </summary>
/// <param name="str">需要计算的字符串</param>
/// <returns>长度值</returns>
private int GetMaxPrefixPostfixLength(string str)
{
int cnt = ;
if (str != null)
{
int len = str.Length - ;
for (int i = ; i <= len; i++)
{
string pre = str.Substring(, i);
string post = str.Substring(str.Length - i, i);
if (pre == post)
cnt = cnt < i ? i : cnt;
}
}
return cnt;
} /// <summary>
/// 计算给定字符串各个字符对应的偏移值
/// </summary>
private void GenerateOffsetArray()
{
if (string.IsNullOrEmpty(data))
return;
if (data.Length == )
return;
for (int i = ; i < data.Length; i++)
{
string sub = data.Substring(, i + );
int max = GetMaxPrefixPostfixLength(sub);
OffsetArray.Add(max);
}
} /// <summary>
/// 从部分匹配表中,取出相应的值
/// </summary>
/// <param name="i"></param>
/// <returns></returns>
public int GetOffset(int i)
{
int val = ;
if (OffsetArray.Count > i)
val = OffsetArray[i];
return val;
} /// <summary>
/// 调试用的,打印计算结果
/// </summary>
public void PrintDic()
{
int cnt = data.Length;
for (int i = ; i < cnt; i++)
{
System.Diagnostics.Debug.WriteLine("{0},{1}\n", data[i], OffsetArray[i]);
}
}
}
}
using System.Collections.Generic; namespace KMPImplementation
{
/// <summary>
/// 该类实现了KMP匹配算法,以此在目标串中查找匹配模式的index
/// </summary>
public class KMPImplementation
{
private string pattern; // 记录模式
private string data;// 记录目标串
PartialMatchTable si;// 记录部分匹配表 /// <summary>
/// 在构造函数中,将异常的输入,如null,过滤处理
/// </summary>
/// <param name="dt">需要匹配的目标串</param>
/// <param name="ptn">匹配模式</param>
public KMPImplementation(ref string dt, string ptn)
{
si = new PartialMatchTable(ptn);
if (dt == null || ptn == null)
{
data = string.Empty;
pattern = string.Empty;
}
else
{
data = dt;
pattern = ptn;
}
} /// <summary>
/// 查找目标串中的第一个匹配项的index
/// </summary>
/// <returns></returns>
public int FindFirstIndex()
{
int idx = -;
int datalen = data.Length;
int patternlen = pattern.Length;
// 空串查找空串的情况
if (datalen == patternlen && patternlen == )
return ;
// 对应目标串比模式短的情况,直接返回找不到,即是-1
if (datalen >= patternlen)
{
datalen = datalen - patternlen;
for (int i = ; i <= datalen; )
{
for (int j = ; j < patternlen; )
{
if (data[i + j] == pattern[j])// 模式与目标串的字符相同,继续比较下一个
{
j++;
if (j == patternlen)// 当模式的index指到了最后一个位置,表明查找到了
return i;
}
else// 当模式与目标串不匹配时
{
if (j == )// 如果第一个字符都不匹配,继续比较下一个位置
i++;
else
i += j - si.GetOffset(j - );// 如果已经发生了部分匹配,查找部分匹配表来确定,当前应该将目标串的index向后移动的量
break;
}
}
}
}
return idx;
} /// <summary>
/// 查找目标串中的所有匹配项的index,以List形式返回
/// </summary>
/// <returns></returns>
public List<int> FindAllIndex()
{
List<int> list = new List<int>();
int datalen = data.Length;
int patternlen = pattern.Length;
// 空串查找空串的情况
if (datalen == patternlen && patternlen == )
{
list.Add();
return list;
}
// 对应目标串比模式短的情况,直接返回找不到,即是-1
if (datalen >= patternlen)
{
datalen = datalen - patternlen;
for (int i = ; i <= datalen; )
{
for (int j = ; j < patternlen; )
{
if (data[i + j] == pattern[j])// 模式与目标串的字符相同,继续比较下一个
{
j++;
if (j == patternlen)// 当模式的index指到了最后一个位置,表明查找到了
{
list.Add(i);
i++;
}
}
else// 当模式与目标串不匹配时
{
if (j == )// 如果第一个字符都不匹配,继续比较下一个位置
i++;
else
i += j - si.GetOffset(j - );// 如果已经发生了部分匹配,查找部分匹配表来确定,当前应该将目标串的index向后移动的量
break;
}
}
}
}
if (list.Count == )
list.Add(-);
return list;
}
}
}
这里实现了两个方法,一个是查找第一个匹配项,一个是查找所有的匹配项,方便调用;但是,显而易见的是,两个方法有太多的相同的地方,可以再做一次抽象。懒病犯了,就没接着改进了。
KMP算法的实现的更多相关文章
- C++经典KMP算法的实现
#include <iostream> #include <algorithm> #include <vector> #include <string> ...
- KMP算法的实现(Java语言描述)
标签:it KMP算法是模式匹配专用算法. 它是在已知模式串的next或nextval数组的基础上执行的.如果不知道它们二者之一,就没法使用KMP算法,因此我们需要计算它们. KMP算法由两部分组成: ...
- 【字符串匹配】KMP算法和next数组的c/c++实现
KMP算法基本思想有许多博客都写到了,写得也十分形象,不懂得可以参考下面的传送门,我就不解释基本思想了.本文主要给出KMP算法及next数组的计算方法(主要是很多网上的代码本人(相信应该是许多人吧)看 ...
- Bug2算法的实现(RobotBASIC环境中仿真)
移动机器人智能的一个重要标志就是自主导航,而实现机器人自主导航有个基本要求--避障.之前简单介绍过Bug避障算法,但仅仅了解大致理论而不亲自动手实现一遍很难有深刻的印象,只能说似懂非懂.我不是天才,不 ...
- Canny边缘检测算法的实现
图像边缘信息主要集中在高频段,通常说图像锐化或检测边缘,实质就是高频滤波.我们知道微分运算是求信号的变化率,具有加强高频分量的作用.在空域运算中来说,对图像的锐化就是计算微分.由于数字图像的离散信号, ...
- java基础解析系列(四)---LinkedHashMap的原理及LRU算法的实现
java基础解析系列(四)---LinkedHashMap的原理及LRU算法的实现 java基础解析系列(一)---String.StringBuffer.StringBuilder java基础解析 ...
- SSE图像算法优化系列十三:超高速BoxBlur算法的实现和优化(Opencv的速度的五倍)
在SSE图像算法优化系列五:超高速指数模糊算法的实现和优化(10000*10000在100ms左右实现) 一文中,我曾经说过优化后的ExpBlur比BoxBlur还要快,那个时候我比较的BoxBlur ...
- 详解Linux内核红黑树算法的实现
转自:https://blog.csdn.net/npy_lp/article/details/7420689 内核源码:linux-2.6.38.8.tar.bz2 关于二叉查找树的概念请参考博文& ...
- 详细MATLAB 中BP神经网络算法的实现
MATLAB 中BP神经网络算法的实现 BP神经网络算法提供了一种普遍并且实用的方法从样例中学习值为实数.离散值或者向量的函数,这里就简单介绍一下如何用MATLAB编程实现该算法. 具体步骤 这里 ...
随机推荐
- java常用的环境变量配置
JDK配置 JAVA_HOME: C:\java\jdk1.7.0 CLASSPATH: .;%JAVA_HOME%\lib\dt.jar;%JAVA_HOME%\lib\tools.jar; PAT ...
- dotTrace 学习笔记
KEYGEN!你懂的(点击下载),仅供学习参考! jetbrains 全系列产品,仅支持最新版本(Ultimate 版本),源码就不提供了,感兴趣的自行反编译一下,未混淆.
- TOGAF架构开发方法(ADM)之架构变更管理阶段
TOGAF架构开发方法(ADM)之架构变更管理阶段 1.10 架构变更管理(Architecture Change Management) 企业架构开发方法各阶段——架构变更管理 1.10.1 目标 ...
- jQuery动态操作表单
<html> <head> <title>jquery表格操作</title> <script language="javascript ...
- Extjs4.2 Tree使用技巧
Extjs4.2 Tree使用技巧小结demo 本案例使用了Ext.Tree.Panel的如下知识点: 1.刷新.重新加载Tree,定位到上次的节点位置 2.Tree的右键操作 3.Extjs4.x ...
- Redis监控数据分布工具Redis-audit 使用总结
Redis-audit 是一个用ruby实现的脚本,通过它,我们可以知道每一类 key 对内存的使用量.它可以提供的数据有:某一类 key 值的访问频率如何,有多少值设置了过期时间,某一类 key 值 ...
- Tomcat启动时卡在“INFO: Deploying web application directory ”
今天在linux上的tomcat部署一个网站时,在刚启动tomcat的时候提示启动成功,然后也能访问成功. 可是第二次启动时虽然没有报错,但无法访问tomcat,查看了catalina.out日志,发 ...
- 用php 进行对文件的操作 (上)
如何让自己磁盘中的文件夹和目录显示在网页上?那就来看一下,用php是怎么来操作他们的吧 php中文件,一般包含两块内容,文件和目录 先来一句一句的看代码,及他的作用 运行后看一下结果 file 指的是 ...
- 导入导出csv文件
在工作中需要把csv文件数据导入数据库或者把数据库数据导出为csv文件.以下是我的简单的实现. <?php class csv { public $db_connection; public $ ...
- 使用pip安装报错的处理方法
在新的机子上使用pip安装程序一直报错: Retrying (Retry(total=4, connect=None, read=None, redirect=None)) after connect ...