云题海 - 专业文章范例文档资料分享平台

当前位置:首页 > 匹配算法一

匹配算法一

  • 62 次阅读
  • 3 次下载
  • 2025/5/3 22:41:43

现在就该位运算出场了,对,这个算法的思路是很笨,但是我位运算的效率高呀,事先我算出字母表中每个字符在模式中出现的位置,用位的方式存在整数里,出现的地方标为0,不出现的地方标为1,这样总共使用σ个整数;同样,我用一个整数来表示升级状态,某个级别有人就标为0,没人就标为1,整个系统升级就恰好可以用“移位”来进行,当检查位置的时候只需要与表示状态的整数“或”1次,所以整个算法就成O(n)了。Shift-Or算法名字就是这样来的。

有一个地方很奇怪,0和1的设定和通常的习惯相反呀,习惯上,喜欢把存在设为1,不存在设为0的。不过这里没有办法,因为移位新移出来的是0。

这时我们来看代码就容易理解多了: 1. #define WORDSIZE sizeof(int)*8

2. #define ASIZE 256

3.

4. int preSo(const char *x, int m, unsigned int S[]) {

5. unsigned int j, lim;

6. int i;

7. for (i = 0; i < ASIZE; ++i)

8. S[i] = ~0;

9. for (lim = i = 0, j = 1; i < m; ++i, j <<= 1) {

10. S[x[i]] &= ~j;

11. lim |= j;

12. }

13. lim = ~(lim>>1);

14. return(lim);

15. }

16.

17. void SO(const char *x, int m, const char *y, int n) {

18. unsigned int lim, state;

19. unsigned int S[ASIZE];

20. int j;

21. if (m > WORDSIZE)

22. error(\

23.

24. /* Preprocessing */

25. lim = preSo(x, m, S);

26.

27. /* Searching */

28. for (state = ~0, j = 0; j < n; ++j) {

29. state = (state<<1) | S[y[j]];

30. if (state < lim)

31. OUTPUT(j - m + 1);

32. }

33. }

代码中lim变量其实就是一个标尺,例如出现最高级的状态是01111111,那么lim就成了10000000,因此只要小于lim,就表示最高级上的0出现了。

原文中对Shift-Or算法的描述还是很难懂的,如果对着那段说明去看代码,有点不知所云的感觉。我还是直接对着代码才想出这个升级的比喻来。

四、可以滑动多远

记得在穷举法中,每一趟比较后,无论成与不成,都将模式向右滑动一个位置,然后继续比

较。有没有办法能利用之前的比较结果,使得模式滑动的更远一点呢?

在介绍经典的KMP算法前,我先介绍几个简单的滑动类算法。

Not So Naive 同名字一样,这个算法的确有点幼稚,它根据模式的前两个字符是否相同来滑动比穷举法稍长一点的距离:如果前两个字符相同,那么文本中与第二个字符不同则必然也与第一个不同;如果前两个字符不同,则与第二个相同的文本字符必然与第一个不同。

那么这两种情况下不用比较都可以断定,文本字符与模式的第一个字符肯定不相同,于是能比穷举法多滑动1个位置。

代码见下:

1. void NSN(char *x, int m, char *y, int n) {

2. int j, k, ell;

3.

4. /* Preprocessing */

5. if (x[0] == x[1]) {

6. k = 2;

7. ell = 1;

8. }

9. else {

10. k = 1;

11. ell = 2;

12. } 13.

14. /* Searching */

15. j = 0;

16. while (j <= n - m)

17. if (x[1] != y[j + 1])

18. j += k;

19. else {

20. if (memcmp(x + 2, y + j + 2, m - 2) == 0 &

21. x[0] == y[j])

22. OUTPUT(j);

23. j += ell;

24. } 25. } 26. 27.

这个算法仅需要常数时间和空间的预处理,比较过程中,先比较模式第二个字符,然后比较其余位置,为的就在某些情况下省掉第一个字符的比较,达到滑动的目的。不过复杂度依然是O(mn)的,比起穷举法或者有轻微改善吧。

想法的确够幼稚,仅仅只考虑了两个模式字符,滑动的步子也太小,能否考虑的更多一点呢?下面请看Quick Search算法。

Quick Search

见到这个名字,不禁让人想起快速排序了,快速排序在最坏情况下是n平方的复杂度,而通常情况下速度超级快,Quick Search莫非也是这样的?没错,就是这样,这个算法在模式长度短而字母表大时,有着优异的表现,尽管它的搜索时间复杂度是O(mn)。

算法的思想是这样,如果文本中某个字符根本就没在模式中出现过,那么就不需要再去和模式中的任何一个比较;如果该字符出现过,那么为了不漏掉可能的匹配,只好与最晚出现过的位置对齐进行比较了。

代码如下:

1. void preQsBc(char *x, int m, int qsBc[]) {

2. int i;

搜索更多关于: 匹配算法一 的文档
  • 收藏
  • 违规举报
  • 版权认领
下载文档10.00 元 加入VIP免费下载
推荐下载
本文作者:...

共分享92篇相关文档

文档简介:

现在就该位运算出场了,对,这个算法的思路是很笨,但是我位运算的效率高呀,事先我算出字母表中每个字符在模式中出现的位置,用位的方式存在整数里,出现的地方标为0,不出现的地方标为1,这样总共使用σ个整数;同样,我用一个整数来表示升级状态,某个级别有人就标为0,没人就标为1,整个系统升级就恰好可以用“移位”来进行,当检查位置的时候只需要与表示状态的整数“或”1次,所以整个算法就成O(n)了。Shift-Or算法名字就是这样来的。 有一个地方很奇怪,0和1的设定和通常的习惯相反呀,习惯上,喜欢把存在设为1,不存在设为0的。不过这里没有办法,因为移位新移出来的是0。 这时我们来看代码就容易理解多了: 1. #define WORDSIZE sizeof(int)*8 2. #define ASIZE 256 3.

× 游客快捷下载通道(下载后可以自由复制和排版)
单篇付费下载
限时特价:10 元/份 原价:20元
VIP包月下载
特价:29 元/月 原价:99元
低至 0.3 元/份 每月下载150
全站内容免费自由复制
VIP包月下载
特价:29 元/月 原价:99元
低至 0.3 元/份 每月下载150
全站内容免费自由复制
注:下载文档有可能“只有目录或者内容不全”等情况,请下载之前注意辨别,如果您已付费且无法下载或内容有问题,请联系我们协助你处理。
微信:fanwen365 QQ:370150219
Copyright © 云题海 All Rights Reserved. 苏ICP备16052595号-3 网站地图 客服QQ:370150219 邮箱:370150219@qq.com