WM算法详解
wm算法 java实现

wm算法 java实现一、引言wm算法(Wagner-Fisher algorithm)是一种常用的字符串匹配算法,用于计算两个字符串之间的编辑距离(edit distance)。
编辑距离是指将一个字符串转换成另一个字符串所需的最少操作次数,操作包括插入、删除和替换字符。
wm算法通过动态规划的方式,计算出两个字符串之间的编辑距离,并可以根据需要获取具体的编辑操作序列。
二、算法原理wm算法的核心思想是将两个字符串进行逐个字符的比较,并计算出字符之间的编辑代价,然后根据代价的大小进行相应的操作。
具体步骤如下:1. 初始化一个二维数组dp,dp[i][j]表示字符串s1的前i个字符与字符串s2的前j个字符之间的编辑距离。
2. 初始化边界条件,即当i=0时,dp[0][j]等于j,表示将s1的空字符串转换成s2的前j个字符所需的操作次数;当j=0时,dp[i][0]等于i,表示将s2的空字符串转换成s1的前i个字符所需的操作次数。
3. 遍历字符串s1和s2的所有字符,计算dp[i][j]:- 当s1的第i个字符等于s2的第j个字符时,dp[i][j]等于dp[i-1][j-1],表示不需要进行修改操作;- 当s1的第i个字符不等于s2的第j个字符时,dp[i][j]等于dp[i-1][j-1]+1,表示需要进行替换操作;- dp[i][j]还可能等于dp[i-1][j]+1(表示删除操作)或dp[i][j-1]+1(表示插入操作),取其中的最小值。
4. 最终dp[m][n]即为字符串s1和s2之间的编辑距离,其中m和n分别为字符串s1和s2的长度。
三、Java实现下面是wm算法的Java实现代码示例:```public class WmAlgorithm {public static int getEditDistance(String s1, String s2) {int m = s1.length();int n = s2.length();int[][] dp = new int[m + 1][n + 1];for (int i = 0; i <= m; i++) {dp[i][0] = i;}for (int j = 0; j <= n; j++) {dp[0][j] = j;}for (int i = 1; i <= m; i++) {for (int j = 1; j <= n; j++) {if (s1.charAt(i - 1) == s2.charAt(j - 1)) {dp[i][j] = dp[i - 1][j - 1];} else {int replace = dp[i - 1][j - 1] + 1;int delete = dp[i - 1][j] + 1;int insert = dp[i][j - 1] + 1;dp[i][j] = Math.min(replace, Math.min(delete, insert));}}}return dp[m][n];}public static void main(String[] args) {String s1 = "kitten";String s2 = "sitting";int editDistance = getEditDistance(s1, s2);System.out.println("编辑距离为:" + editDistance);}}```以上代码中,getEditDistance方法接收两个字符串s1和s2作为参数,并返回它们之间的编辑距离。
QWM算法在网页分类中的应用

随着互联 网发展和 I T技术的普及 , 网络和信息技术已经 日渐深入到 日常生活和工作 当中,社会信息化和信息网络化 ,突破 了应用信息在时间和空间上的障碍 ,使信息的价 值 不断提高 。然 而互联 网恰如一 柄 ” 刃剑 ” 双 ,为 人们工 作带来 便 利 的同时 ,伴 随着 的是 日 趋严重的网络信息安全问题 。例如反动、色情、迷信等有碍社会公德的信息和网页篡 改 、计算机病 毒 、系统 非法 入侵等 信息 安全 隐患 出现 于 网络 中 。面对 信息 安全 的严峻 考 验,为有效遏制不法分子通过 We 发布不良信息 , b 可通过对 网页进行监听、还原 , 对网 页类型进行识别, 及时发现其 中可能出现的不 良信息内容, 打击和防范利 用互联 网进行的 不法活动,从而对网络信息安全提供保障。 目 We 服务是互联 网上最重要 , 前 b 最广泛的应用之一 。 而超文本传输协议 H T 作 TP 为 We b服 务数据 的传输 通道 ,成 为互联 网上最 常 见 ,最 重要 的应 用协议 之一 。从 19 90 年起在 www 上被广泛使用,互联 网上基于 H T T P的应 用很多,主要包括 We b邮件、
论 坛、聊天 室 、博客 等 。本文通 过对 HT P协议 及 网页应 用类型 的研究 ,给 出一种 应 用 T
于网页分类 的快速多模式匹配算法一一Q wM 算法。
2 HT P 协 议 分 析 T
超文本信息传输协议 H T ( ye T x Tas r r oo [, 是从客户机/ T PH pr et r f o c1 1 】 n eP t ) 2 服务器模 型 发展起来 的 ,是通 用的 、无状态 的、面 向对 象 的协议 。 HT P 的会话 期 分为 四个步骤 :客 户端程 序与 服务 器建立 连接 后 ,发送请 求 ,服务 T 器进行响应 , 最后关闭连接 。 早期版本每次连接只处理一个请求 , T P1 版本进行改 H T /. 1 进 ,使用持续连接 。当客户或服务器准备关闭连接 , 通知另一端 ,然后关闭连接。 21客户端请求信息 . 在 申请互联网上的信息时, 用户输入 U L告诉客户端程序信息在网络中的位置 。 R 客 户端程序得到 U L后 ,通过 T PI R C/ P和主机建立连接 ,向服务器发送请求。请求信息有 开始行 ( 请求行)、信息头、信息体组成。请求信息格式如图 1 所示。
《WM控制技术本》课件

05 WM控制系统的实现与优 化
WM控制系统的实现方法
确定控制目标
明确WM控制系统的控制目标,如提 高生产效率、降低能耗等。
硬件选型与配置
根据控制需求选择合适的硬件设备, 如传感器、执行器、控制器等,并进 行合理配置。
控制系统设计
根据硬件设备和控制需求,设计WM 控制系统的控制算法、控制逻辑和控 制界面等。
引入智能控制技术,如神经网络、模糊控 制等,对WM控制系统进行优化。
WM控制系统的性能测试与评估
测试环境搭建
搭建WM控制系统性能测试的环境,包括测试平台、测试设备和测试 软件等。
性能测试
对WM控制系统进行性能测试,包括控制精度、响应速度、稳定性等 指标的测试。
测试结果分析
对测试结果进行分析,找出系统存在的问题和不足,提出改进措施。
控制系统组成
01
02
03
控制系统基本结构
输入、控制器、执行器、 被控对象和输出等组成部 分的详细介绍。
控制器设计方法
比例、积分、微分等基本 控制规律的介绍,以及 PID控制器的设计和应用 。
执行器和被控对象
执行器的种类和特性,被 控对象的数学模型和特性 分析。
控制系统的分类
开环控制系统和闭环控制系统
实际调试
在实际环境中对控制系统进行 调试,确保系统性能达到预期 要求。
需求分析
明确控制目标、工艺要求和约 束条件,为后续设计提供依据 。
仿真测试
通过仿真测试验证控制方案的 可行性和有效性,发现问题及 时调整。
文档编写
整理设计过程和结果,编写技 术文档,为后续维护和升级提 供参考。
WM控制系统的设计实例
动态性能分析
控制系统的动态响应过程 和性能指标,如超调量、 调节时间、稳态误差等。
基于MWM算法的多模式匹配的改进算法NMWM

得哈 希 值, 记为 index, 以此
图 3 前缀表
来确定要遍历的模式子集。取 Pat Array[ index ] 为
首节点, 依次往后 移动 NumArray [ index ] 个模式
为末节点, 遍历匹配该子集的模式, 找出和文本发
生匹配的模式, 转到步骤 4) 。
4) 若检测到模式匹配成功, 则输出模式串, 并
摘 要 针对入侵检测软件 snort 的默认多模式匹配算法- M W M ( M odified W u- M anber ) 中存在模 式匹配窗口 移动 距离偏小和缺少合适的哈希冲突处理的问题, 对算法的模式集预处理阶段和文 本匹配阶 段进行了改 进, 设 计和实现了 一种 新的多模式匹配算法- N M WM 算法。实验结果表明, N M W M 算法比 M W M 算法能够有效的提高模式 匹配的处理速度。
Key words intrusio n detection, multi pa ttern m atching, M W M alg o rithm, N M W M algo rithm Class Number T P393. 08
1 引言
近年来随着网络技术的发展, 网络传输数据量 越来越大, 这样就对网络安全提出了新的要求, 入 侵检测系统如何在高速网络环境下实时有效地正 常工作成为研究重点之一。目前大多数基于特征 的模式 匹 配 技术 的 入 侵 检测 系 统 很 难处 理 100M pbs 网络满负荷时的数据 量, 对分 布式传输 数据的处理更是难以达到的目标。本文以面向高 速网络环境下基于特征模式匹配技术的入侵检测 系统为研究目标, 设计了一种高效的多模式匹配算 法, 并用实验证明了改进算法的高效性。
总第 227 期 2008 年第 9 期
WM技术培训课件

WM技术培训
8
数字脉宽调制(PWM)方法
实现方法
三角载波是为了形象说明调制原理而借用或用模拟电路产生
PWM时必须采用的波形,在用数字化实现时,三角载波实际上是不 存在的,完全由软件来代替了,这样既可以减少硬件投资又可以 提高系统可靠性。
不同调制波生成的PWM脉宽对于变频效果,比如输出基波电压幅值,
WM技术培训
5
单极性调制和双极性调制
单极性调制
在调制波的半个周期内三角载波只在一个方向变化, 所得到输出电压的PWM波形也在一个方向变化的控 制方式称为单极性PWM控制方式。
双极性调制
在调制波的半个周期内三角载波正负方向变化,所得 到输出电压的PWM波形也在正负方向变化的控制方式 称为双极性PWM控制方式。
(3)
WM技术培训
19
ISG SVPWM采用(d)
WM技术培训
20
ISG MCU 软件实现
第一步:如图所示: 通过电流调节器输出直轴和交轴参考电压 ,通过Parke和 Clarke逆变换得到三相电压,根据式(2)取 k=0.5得到三相调制波信号
第二步:根据式(1)配置 DSP 比较寄存器,产生SVPWM
取合成矢量的 倍,定义磁势矢量: 由于磁势的大小和电流 成正比,所以电流矢量定义为:
同理,定义三相电机的磁链矢量以及电压矢量为:
忽略定子电阻,磁链可以通过定子电压的积分得到:
为获得电机的圆形旋转磁场,只需要控制三相定子电压的 合成矢量为圆形旋转矢量 即可。
WM技术培训
13
调制原理
对于三相电压型逆变器而言,电机的相电压依赖于它所对应的逆变器桥臂上下功
最小幅值误差过调制
当u*的末端位于六边形之外时,将u*投影到六边形的AB边上,形成以C点为末端的新的电压参考
基于后缀WM匹配算法的改进算法

An I mp r o v e d Al g o r i t h m Ba s e d o n t he S u fi x W M Ma t c hi n g Xi a o g e W U Xi a o ni a n , ZHANG Zh a o
Abs t r a c t Wi t h r e g a r d t o t h e p r o b l e m o f t he r e p e a t e d ma t c hi n g i n W M a l g o r i t h m b a s e d o n s uf f i x ma t c h i n g.a n i mp r o v e d a l g o r i t h m i s p r o p o s e d i n t h i s p a p e r . W he n t h e a l g o r i t h m d e t e c t s t h a t t h e t e x t s t r i n g ha s t he s a me p r e f i x,s uf f i x,a n d s u f f i x o f t he f o r me r m c h a r a c t e r a s t h e p a t t e r n s t r i n g,d u r i n g t he ma t c h i n g s t a ge ,t h e a l g o r i t h m wo u l d s k i p t he l o c a t e d b l o c k s wh i c h h a v e be e n c o nf i m e r d i n t he s c a nn i n g .W h i c h a v o i d r e pe a t e d l y ma t c h i n g t h e c o n f i m e r d b l o c ks ,r e d u c i ng t he ma t c h i n g o v e r h e a d . Th e t e s t e d r e s u l t s s h o w t h a t ,c o mp a r e d wi t h t h e o r i gi n a l a l g o r i t h m ,t h e i mp r o v e d a l g o r i t h m r e d u c e s t he ma t c h i n g t i me ,a n d i mp r o v e s t h e e f f i c i e n c y o f t he s y s t e m. Ke y W or d s mul t i - p a t t e r n ma t c h i n g,W M - a l g o r i t h m ,p r e f i x,s u f f i x Cl a s s Nu mb e r TP 3 9 3 . 0 8
第07章_模糊规则_WM算法
模糊控制系统
模糊控制系统理论于20世纪60年代产生由Zadeh提出。它是一种基 于规则或者知识的系统,用以描述现实世界。模糊系统通常用于对模 糊的对象进行描述,但其理论本身却是精确的。 使用模糊系统理论可以对复杂工业系统进行精确定义,在不了解对象 运行机制的情况下对其进行数学建模,创建适合实际应用需求的模糊 控制系统。 目前较常见的模糊系统主要有以下三类:
1. 对于规则库中的每一条规则,确定其隶属度; 2. 计算规则库中的每一条规则的支持度; 3. 对于给定的输入A’,使用下式获得其输出B’:
xU
B ' ( y ) sup t[ A ' ( x), l ( x, y )]
模糊化和解模糊化
模糊化即:将一个实值x’∈U向U上的模糊集A’进行映射的过程。在 点x’处,模糊集A’必须具有比其它模糊集大的隶属度。 对于模糊化操作,最关键的步骤是隶属度函数的选择,目前主要采用 以下三种隶属度函数:
模糊规则提取研究现状
当模糊系统中存在较多变量或模糊子集划较多时仅领先专家经验产生 规则比较困难,因此,近年来如何通过样本数据提取模糊规则受到较 多关注。一系列研究分别提出使用梯度下降法、最小二乘法、遗传算 法、模糊聚类、神经网络等方法从样本数据中获取模糊规则的相关理 论。 但是,这些理论都存在各种不足,如:效率低,实现较繁琐,学习机 理比较复杂,提起的规则不易理解等。 Wang-Mendel算法是最早提出从数据中直接提取模糊规则而与先 验知识无关的一种从样本数据中提取规则的算法,由Wang和 Mendel两人提出。该方法简单易用且无需了解对象内在机制,目前 已成为模糊规则提取领域被广为应用的经典算法。
A' ( x) e
(
wm_concat date变科学计数法 -回复
wm_concat date变科学计数法-回复什么是科学计数法?科学计数法(Scientific Notation),也被称为标准形式,是一种用于表示非常大或非常小的数字的方法。
它以10的幂的形式表示,其中基数在1和10之间,而指数被称为这个数字所移动的位数。
科学计数法的目的是使大量或小量的数值更易读和理解。
为什么要使用科学计数法?使用科学计数法有许多好处。
首先,它可以减少数字的位数,使其更易读。
例如,1,000,000可以简化为1 x 10^6,只用3个字符就能表示,而不是7个。
其次,科学计数法可以方便地进行大量和小量之间的比较。
例如,1 x 10^9和1 x 10^12之间的数量级差异很大,而在科学计数法中,可以轻松地进行比较和理解。
此外,在科学领域,科学计数法可以更方便地表示微观和宏观领域的数值,如原子和星系的数量。
如何将数字转换为科学计数法?将数字转换为科学计数法需要以下步骤:1. 确定一个数值,然后确定基数(介于1和10之间)和指数(表示数字的位移)。
2. 将数值中的小数点向左移动或向右移动,直到小数点位于非零第一位之后,形成一个数字介于1和10之间的值。
3. 计算移动过程中小数点的位数,并将其作为指数的绝对值。
4. 根据移动方向来确定指数的正负。
如果小数点向左移动,指数为正数;如果小数点向右移动,指数为负数。
5. 用基数和指数的形式表示原始的数值。
举例说明:假设要将2,540,000转换为科学计数法。
1. 确定数值为2.54,并确定基数介于1和10之间。
2. 将小数点向左移动6位,直到小数点位于非零第一位之后,得到2.54的值。
3. 移动过程中小数点的位数为6,作为指数的绝对值。
4. 小数点向左移动,因此指数为正数,即6。
5. 使用基数和指数的形式表示原始的数值,即2.54 x 10^6,结果就是2,540,000的科学计数法表示。
科学计数法在科学研究、工程领域、天文学和物理学等领域中具有重要的应用。
广告点击预测算法-LR
互联网广告综述之点击率预测系统(Logistic Regression)点击率预测是互联网广告业内普遍认可的评估流量质量的方法。
DSP 方可以在投放广告之前,借助点击率预测判断SSP 的请求广告是否满足不同广告主的投放需求(有些广告主能接受一定的单价要求一定的点击次数,有些广告主要求一定广告费内用获取一定的交互次数),从而达到优化广告,提高广告效益的目的。
从数据的角度,广告点击率的预估实际上是使用广告数据和用户数据的一次模型运算。
一般情况下不同类型的用户对某广告类型的点击率与最终是否点击的呈线性回归表示,故CTR 预测使用的逻辑算法的进行评估:z =w 0+w 1∗x 1+w 2∗x 2+⋯+w m ∗x mx 1、x 2、x 3……x m 是每个样本的m 个特征,w 0、w 1、w 2……w m 为每个特征值的权重。
按照sigmoid 函数形式求出:g (z )=1/(1+e −z )sigmoid 函数定义域(-INF,INF )而值域在(0,1)之间,方便逻辑回归函数对两分类的目标值进行分类。
P =π(x)=1/(1+e −z )将sigmoid 函数可以看作样本的概率密度函数,每个样本点可以通过sigmoid 函数求出对应的概率。
那么权重W 0、W 1、W 2……W m 则需要最大似然率(MLE )和优化算法来求出。
L (β)=∏π(x )y i mi=0π(x)1−y i上述为最大似然率公式,对其求导则可以得到:∑[y i −π(x i )]=∑[y i −e β0+β1x 1……βm x m 1+e β0+β1x 1……βm x m ]ni=1n i=1=0 ∑x ij [y i −π(x i )]=∑[y i −e β0+β1x 1……βm x m 1+e β0+β1x 1……βm x m ]ni=1n i=1=0 J=1,2,3,……p----p 为独立向量个数。
上式称为似然方程。
基于WM算法的多模式匹配改进算法WMN
摘
要 : 侵 检 测 系统 中有 部 分 时 间 用 来进 行 模 式 匹配 , 入 因此提 高模 式 匹配 算 法 的 处理 速 度 具 有 重 要 的 意 义 从 两个 方 面 改进 了
目前 公认 效 率较 高的 多模 式 匹配算 法 WM, 计 出 WM 算 法 , 对 该 算 法进 行 了性 能 测试 和分 析 。 设 N 并 实验证 明该 文提 出的 WMN 算 法 能 够有 效提 高模 式 匹配 的 处理 速 度 。 关键 词 : 式 匹配 算 法 ; 模 WM 算 法 : WMN 算 法
维普资讯
18 2
2 0 ,3 1 ) 0 7 4 (5
C m u r E gn eig a d A p i t n o p t n i r n p l ai s计 算机 工 程 与应 用 e e n c o
基 于 WM 算法的多模 式 匹配改进算法 WMN
YUANS i z o g. h — h n CAO i W ANG n y n I r v d p te n ma c i g ag rt m a e n W M . mp t r n i e rn M n, Ya — a .mp o e a t r t h n l o i h b sd o Co u e E g n e i g
a d Ap l ain , 0 7, 3 1 :2 - 3 . n pi t s 2 0 4 ( so ee t n s se awa s s e d o t n p t r mac i g t u p e i g p t r t h n l o t m s r c : h n r in d tc i y tm l y p n s s me i o at n u o me e t hn ,h s s e d n a t n ma c i g ag r h e i i a sg i c n r s a c . h s a e p e e t s i nf a t e e r hT i p p r r s n s n i r v d atr mac ig ag r h , ald W MN, wh c t e d pi ae i a mp o e p t n e th n l o t m c l i e i n ih h u l t c
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
WM算法详解WM算法采用字符块技术,增大了主串和模式串不匹配的可能性,从而增加了直接跳跃的机会。
使用散列表选择模式串集合中的一个子集与当前文本进行完全匹配。
使用前缀表进一步过滤不匹配的模式串,使算法获得了较高的运行效率。
WM算法首先对模式串集合进行预处理。
预处理阶段将建立3个表格:SHIFT表,HASH 表和PREFIX表。
SHIFT表用于在扫描文本串的时候,根据读入字符串决定可以跳过的字符数,如果相应的跳跃值为0,则说明可能产生匹配。
HASH表用来存储尾块字符散列值相同的模式串。
PREFIX表用于存储尾块字符散列值相同的模式串的首块字符散列值。
假设模式串集合P中最短的模式长度为m,那么,后续仅考虑所有模式的前m个字符组成的模式串。
设X=x1…xB为T中的待比较的长度为B的子串,通过hash函数映像得到一个索引值index,以该索引值作为偏移得到SHIFT表中的值,该值决定读到当前子串x后可以跳过的位数。
假设X映射到SHIFT表的入口为index的表项,即index=hash(x)。
SHIFT表中值的计算原则为:(1)如果X不出现在模式串中,则SHIFT[h]=m-B+1。
(2)如果X出现在某些模式串中,而且在所有的模式串中的最右出现位置为q,则SHIFT[h]=m-q。
算法匹配的大致原理:(1)设当前比较的文本串X的hash值为h。
如果SHIFT[h]=0,说明可能产生了匹配,那么需要进一步的判断。
(2)用该h值作为索引,查HASH表找到HASH[h],它存储的是指标,指向两个单独的表:一个是模式链表,另一个是PREFIX表。
模式链表中存放的是后B个字符的hash值同为h的所有模式。
(3)对于待比较长度为m的串,如果其长度为B的前缀与模式的前缀的hash值也相同,则再将相应的文本串与符合的模式逐一进行比较,最终判定是否完全匹配。
算法匹配的主要过程:基于后缀的模式匹配,每次扫描B个字符T[m-B+1]…..T[m]。
(1)扫描text的末B位T[m-B+1]…..T[m]通过hash function计算其哈希值h。
(2)查表,SHIFT[h]>0,text小指针后滑SHIFT[h]位,执行(1);SHIFT[h]=0,执行那个(3)。
(3)计算此m位text的前缀的哈希值,记为text_prefix。
(4)对于每个p(HASH[h]≦p<HASH[h+1]),看是否PREFIX[p]=text_prefix。
(5)如果相等,让真正的模式串去和text匹配。
WM算法的代码网上已经有了,下面给出其中的一个参考:/index.php/post/1338.html这段代码对于初学者可能还是比较的晦涩,下面给出对这份代码的详细注释以及流程图。
首先给出的是对代码的详细注释:#ifndef WM_H#define WM_H#include <stdio.h>#include <stdlib.h>#include <string.h>#define HASHTABLESIZE (256*256)#define MAXLEN 256typedef struct wm_pattern_struct//每个模式串的结构{struct wm_pattern_struct *next;//指向下一个模式串unsigned char *psPat; //pattern array//模式串数组unsigned psLen; //length of pattern in bytes//模式串的长度}WM_PATTERN_STRUCT;#define HASH_TYPE short#define SHIFTTABLESIZE (256*256)typedef struct wm_struct//模式串集的结构{WM_PATTERN_STRUCT *plist; //pattern list//模式串列表WM_PATTERN_STRUCT *msPatArray; //array of patterns//模式串转变为WM_PATTERN_STRUCT后的结构unsigned short *msNumArray; //array of group counts, # of patterns in each hash group int msNumPatterns; //number of patterns loaded//模式串的个数unsigned msNumHashEntries;//HASH表的大小HASH_TYPE *msHash; //last 2 characters pattern hash table//HASH表unsigned char* msShift; //bad word shift table//SHIFT表HASH_TYPE *msPrefix; //first 2 characters prefix table//PREFIX表int msSmallest; //shortest length of all patterns//最短模式串的长度}WM_STRUCT;WM_STRUCT * wmNew();void wmFree(WM_STRUCT *ps);int wmAddPattern(WM_STRUCT *ps,unsignedchar *P,int m);int wmPrepPatterns(WM_STRUCT *ps);void wmSearch(WM_STRUCT *ps,unsigned char*Tx,int n);#endifWM.c文件如下:view plaincopy toclipboardprint?#include <stdio.h>#include <string.h>#include <stdlib.h>#include <ctype.h>#include "wm.h"extern int nline=1;extern int nfound=0;#define MAXN 10001 //模式串的最大长度MAXN –1#define MAXM 51//单词最大长度为MAXM –1 WM_STRUCT * wmNew(){WM_STRUCT *p=(WM_STRUCT *)malloc(sizeof (WM_STRUCT));if(!p) return 0;p->msNumPatterns=0;p->msSmallest=1000;return p;}void wmFree(WM_STRUCT *ps){if(ps->msPatArray){if(ps->msPatArray->psPat) free(ps->msPatArray->psPat);free(ps->msPatArray );}if(ps->msNumArray) free(ps->msNumArray); if(ps->msHash) free(ps->msHash);if(ps->msPrefix) free(ps->msPrefix);if(ps->msShift) free(ps->msShift);free(ps);}int wmAddPattern(WM_STRUCT *ps,unsigned char *q,int m)//m字符串长度,模式串转变为WM_STRUCT结构{/>WM_PATTERN_STRUCT *p;p=(WM_PATTERN_STRUCT *)malloc(sizeof (WM_PATTERN_STRUCT));if(!p) return -1;p->psPat=(unsigned char*)malloc(m+1);memset(p->psPat+m,0,1); //模式串最后一位位0,结束标志memcpy(p->psPat,q,m);p->psLen=m;ps->msNumPatterns++;if(p->psLen<(unsigned)ps->msSmallest) ps->msSmallest=p->psLen;p->next=ps->plist; 有点从后往前插入链表的感觉ps->plist=p;return 0;}static unsigned HASH16(unsigned char *T){return (unsigned short) (((*T)<<8) | *(T+1));}void sort(WM_STRUCT *ps)//字符串哈希值从小到大排列{int m=ps->msSmallest;int i,j;unsigned char *temp;int flag; //该值的作用是,当某一时刻的序列已经从小到大排列时,就无须再进行扫描了for(i=ps->msNumPatterns-1,flag=1;i>0 &&flag;i–) //以下为冒泡排序算法{flag=0;for(j=0;j<i;j++){if(HASH16(&(ps->msPatArray[j+1].psPat[m-2]))<HASH16(&(ps->msPatArray[j].psPat[m-2]))) {flag=1;temp=ps->msPatArray[j+1].psPat;ps->msPatArray[j+1].psPat=ps->msPatArray[j].psPat;ps->msPatArray[j].psPat=temp;}}}}static void wmPrepHashedPatternGroups(WM_STRUCT *ps)//计算有多少个不同哈希值,且从小到大{unsigned sindex,hindex,ningroup;int i;int m=ps->msSmallest;ps->msNumHashEntries=HASHTABLESIZE;ps->msHash=(HASH_TYPE*)malloc(sizeof(HASH_TYPE)* ps->msNumHashEntries);if(!ps->msHash){printf("No memory in wmPrepHashedPatternGroups()\n");return;}for(i=0;i<(int)ps->msNumHashEntries;i++){ps->msHash[i]=(HASH_TYPE)-1;}for(i=0;i<ps->msNumPatterns;i++){hindex=HASH16(&ps->msPatArray[i].psPat[m- 2]);sindex=ps->msHash[hindex]=i;ningroup=1;//此时哈希表已经有序了while((++i<ps->msNumPatterns) &&(hindex==HASH16(&ps->msPatArray[i].psPat[m-2])))ningroup++;ps->msNumArray[sindex]=ningroup;i–;}}static void wmPrepShiftTable(WM_STRUCT*ps)//建立shift表,算出每个字符块要移动的距离,像Horspool算法那样的{int i;unsigned short m,k,cindex;unsigned shift;m=(unsigned short)ps->msSmallest;ps->msShift=(unsigned char*)malloc (SHIFTTABLESIZE*sizeof(char));if(!ps->msShift)return;for(i=0;i<SHIFTTABLESIZE;i++){ps->msShift[i]=(unsigned)(m-2+1);}for(i=0;i<ps->msNumPatterns;i++){for(k=0;k<m-1;k++){shift=(unsigned short)(m-2-k);cindex=((ps->msPatArray[i].psPat[k]<<8) | (ps- >msPatArray[i].psPat[k+1]));//B为2if(shift<ps->msShift[cindex])ps->msShift[cindex]=shift;//k=m-2时,shift=0,}}}static void wmPrepPrefixTable(WM_STRUCT *ps)//建立Prefix表int i;ps->msPrefix=(HASH_TYPE*)malloc(sizeof (HASH_TYPE)* ps->msNumPatterns);if(!ps->msPrefix){printf("No memory in wmPrepPrefixTable()\n"); return;}for(i=0;i<ps->msNumPatterns;i++){ps->msPrefix[i]=HASH16(ps->msPatArray[i].psPat); //对每个模式串的前缀进行哈希}}void wmGroupMatch(WM_STRUCT *ps,//后缀哈希值相同,比较前缀以及整个字符匹配int lindex, //lindex为后缀哈希值相同的那些模式串中的一个模式串的indexunsigned char *Tx,unsigned char *T)WM_PATTERN_STRUCT *patrn;WM_PATTERN_STRUCT *patrnEnd;// int text_prefix;HASH_TYPE text_prefix; //changed by dklkt unsigned char *px,*qx;patrn=&ps->msPatArray[lindex];patrnEnd=patrn+ps->msNumArray[lindex]; //哈希值相同text_prefix=HASH16(T);for(;patrn<patrnEnd;patrn++){if(ps->msPrefix[lindex++]!=text_prefix) continue;else{px=patrn->psPat;qx=T;while(*(px++)==*(qx++) && *(qx-1)!=’\0′); // 整个模式串进行比较if(*(px-1)==’\0′){printf("Match pattern "%s" at line %d column%d\n",patrn->psPat,nline,T-Tx+1);nfound++;}}}}int wmPrepPatterns(WM_STRUCT *ps)//由plist得到msPatArray{int kk;WM_PATTERN_STRUCT *plist;ps->msPatArray=(WM_PATTERN_STRUCT*) malloc(sizeof(WM_PATTERN_STRUCT)*ps->msNumPatterns);if(!ps->msPatArray)return -1;ps->msNumArray=(unsigned short*)malloc (sizeof(short)*ps->msNumPatterns);if(!ps->msNumArray)return -1;for(kk=0,plist=ps->plist;plist!=NULL &&kk<ps->msNumPatterns;plist=plist->next){memcpy(&ps->msPatArray[kk++],plist,sizeof (WM_PATTERN_STRUCT));}sort(ps);wmPrepHashedPatternGroups(ps); wmPrepShiftTable(ps);wmPrepPrefixTable(ps);return 0;}void wmSearch(WM_STRUCT *ps,unsigned char *Tx,int n)//字符串查找{int Tleft,lindex,tshift;unsigned char *T,*Tend,*window;Tleft=n;Tend=Tx+n;if(n<ps->msSmallest)return;//T--------窗口-------Windowfor(T=Tx,window=Tx+ps->msSmallest-1;window<Tend;T++,window++,Tleft–){tshift=ps->msShift[(*(window-1)<<8) |*window];while(tshift) //此时tshift!=0,无匹配{window+=tshift;T+=tshift;Tleft-=tshift;if(window>Tend) return;tshift=ps->msShift[(*(window-1)<<8) |*window];}//tshift=0,表明后缀哈希值已经相同if((lindex=ps->msHash[(*(window-1)<<8) |*window])==(HASH_TYPE)-1) continue;lindex=ps->msHash[(*(window-1)<<8) |*window];wmGroupMatch(ps,lindex,Tx,T); //后缀哈希值相同,比较前缀及整个模式串}}int main(){int length,n;WM_STRUCT *p;char keyword[MAXM]; //单词char str[MAXN]; //模式串p=wmNew();printf("scanf the number of words–>\n"); scanf("%d", &n);printf("scanf the words–>\n");while(n –){scanf("%s", keyword);length=strlen(keyword); wmAddPattern(p,keyword,length);}wmPrepPatterns(p);printf("scanf the text string–>\n"); scanf("%s", str);length=strlen(str);wmSearch(p,str,length);wmFree(p);return(0);}下面部分为程序代码的流程图,有助于更好的理解上面的程序Main(){WM_STRUCT* p=wmNew();--->(1)While(n--)wmAddPattern(p,keyword,klength);--->(2)wmPrepPatterns(p);---->(3)wmSearch(p,str,slength);----->(8)wmFree(p);---->(10)}(1) new(p)以及p的初始化(2) keyword-----add-->p->list(3) plist---得到->msPatArraysort(ps);-->(4)wmPrepHashedpatternsGroup(ps);-->(5)wmPrepShiftTable(ps);-->(6)wmPrepPrefixTable(ps);--->(7)(4)冒泡排序,字符串哈希值从小到大排列(5) HASH表初始化计算有多少个不同哈希值,且从小到大拉链:(6)构建SHIFT表SHIFT[index]= m-B+1;//无匹配min(shift);//最短移动距离(7)构建PREFIX表Ps->msPrefix[i]=HASH16(ps->msPatArray[i].psPat);(8)求tshift若tshift!=0 移动tshift若tshift=0 hash值不存在,continue;wmGroupMatch--->(9)(9) for(;patrn<patrnEnd;patrn++)比较ps->msprefix[index++]和text_prefix若相等,再比较整个模式串(10) free(p)队列构建Trie下面为要构建的树结构:创建两个指针p,q。