Knuth-Morris-Pratt(KMP)串匹配算法(C & assembly)

本文详细介绍Knuth-Morris-Pratt(KMP)串匹配算法的原理与实现,包括如何构造Next数组以及模式匹配过程,并提供了C语言及汇编优化版本的代码示例。

Knuth-Morris-Pratt(缩写KMP)串匹配算法是一个基本的串操作算法,在各种含有串操作的程序中广泛使用。
KMP匹配的最大优点在于——主串无需回溯,故可以用于数据流的匹配,如可顺序读入文件的过程中实现匹配,同时它也是各种匹配算法中速度最快的。

此处给出了算法的C代码。另外,还写了一段汇编优化的参考代码,虽无太大用处但仍可作为汇编优化的参考。程序的编写参考了 清华版 严蔚敏吴伟民著的《数据结构(C 语言版)》

 

  1. #define _USEASM_
  2. //求模式串的Next数组
  3. // p: 模式串
  4. // lp: 模式串长度
  5. inline int * getNext(const char * p, int lp=-1)
  6. {
  7.     if(lp==-1)
  8.         lp=(int)strlen(p);
  9.     //前一个模式串的Next数组
  10.     static int * next=NULL;
  11.     //如果有数据先释放内存
  12.     if(next) delete[] next;
  13.     //为Next数组分配存储空间
  14.     next=new int[lp];
  15.     //计算模式串
  16.     next[0]=-1;
  17.     int i=0; int j=-1;
  18.     while(i<lp-1)
  19.     {
  20.         if(j==-1||p==p[j])
  21.         {
  22.             i++; j++;
  23.             next=j;
  24.         }
  25.         else
  26.             j=next[j];
  27.     }
  28.     return next;
  29. }
  30. //Knuth-Morris-Pratt模式匹配算法
  31. // s: 源串
  32. // p: 模式串
  33. int instr(const char * s, const char * p)
  34. {
  35.     int ls=(int)strlen(s);
  36.     int lp=(int)strlen(p);
  37.     int * next=getNext(p,lp);
  38. #ifndef _USEASM_
  39.     int i=0; int j=0;
  40.     while(i<ls&&j<lp)
  41.     {
  42.         if(s==p[j])
  43.         { i++; j++; }
  44.         else
  45.         {
  46.             j=next[j];
  47.             if(j==-1) { i++; j++; }
  48.         }
  49.     }
  50.     if(i<ls)
  51.         return (i-j);
  52.     else
  53.         return -1;
  54. #else
  55.     _asm
  56.     {
  57.         push edi
  58.         push esi
  59.         push ebx
  60.         push ecx
  61.         push edx
  62.         mov edi, dword ptr[s]
  63.         mov esi, dword ptr[p]
  64.         mov edx, dword ptr[next]
  65.         xor ebx, ebx
  66.         xor ecx, ecx
  67.         _While_:
  68.             cmp ebx, dword ptr[ls]
  69.             jge _EndWhile_  ;大于等于转移
  70.             cmp ecx, dword ptr[lp]
  71.             jge _EndWhile_  ;大于等于转移
  72.             _If_:
  73.                 mov ah, byte ptr[edi+ebx]
  74.                 mov al, byte ptr[esi+ecx]
  75.                 cmp ah,al
  76.                 jnz _Else_
  77.                 ;_If_
  78.                 inc ebx
  79.                 inc ecx
  80.                 jmp _EndIf_
  81.             _Else_:
  82.                 shl ecx, 2
  83.                 mov ecx, dword ptr[edx+ecx]
  84.                 cmp ecx, -1
  85.                 jnz _EndIf_
  86.                     inc ebx
  87.                     inc ecx
  88.             _EndIf_:
  89.             jmp _While_
  90.         _EndWhile_:
  91.         _If2_:
  92.             cmp ebx, dword ptr[ls]
  93.             jge _Else2_
  94.             mov eax, ebx
  95.             sub eax, ecx
  96.             jmp _EndIf2_
  97.         _Else2_:
  98.             mov eax, -1
  99.         _EndIf2_:
  100.         pop edx
  101.         pop ecx
  102.         pop ebx
  103.         pop esi
  104.         pop edi
  105.     }
  106. #endif
  107. }
    (原创文章,转载时请注明本文网址)
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值