zoukankan      html  css  js  c++  java
  • 学点字符串匹配——shiftAnd/shiftOr

      这个算法利用了位运算的优势速度很快,易于实现,缺点是模式串不能太长。据说在适用范围内速度是kmp的至少2倍。算法思想是用一个数字prefix的二进制去表示模式串的前缀,prefix的二进制第i位表示模式串的前缀0~i。如果这个前缀i是当前搜索到的匹配串的后缀时,将第i位至1。算法就是从匹配串的第0个字符到最后一个字符不断更新prefix的值每次更新后看最长的前缀(即模式串)的位是否被至1,如果是说明得到了一个匹配。

      下面说明下更新的过程。假如求出了比较匹配串第j位时的prefix,现在求比较j+1位的情况:prefix第i位为1当且仅当prefix第i-1位为1(匹配了i-1个字符),并且第i位所在字符和匹配串第j+1个字符相等。按下面实现来说,每次循环将prefix左移一位,第0位至一,在&上一个代表第i个字符是否匹配模式串某位的数字(这个通过初始化得到),就得到更新后的prefix。

      shiftAnd和shiftOr的思想一致。只是实现时存的是反码,因为prefix左移自然引入第0位的是0,为了减去或运算,才引入反码表示。

    上代码~

     1 //return a hashtable 代表字母表中的各个元素是否能成为模式串的后缀,用64位位压缩表示
     2 long long * initAlphbat(char *patternString)
     3 {
     4     long long *hash = (long long *) malloc(256 * sizeof(long long));
     5     unsigned int idx = 0;
     6     int psLen = strlen(patternString);
     7 
     8     if(hash == NULL) return NULL;
     9 
    10     memset(hash, 0, 256 * sizeof(long long));
    11     for(idx = 0; idx < psLen; ++idx)
    12     {
    13         hash[(unsigned int)patternString[idx]] |= ((long long)1 << idx); //表示patternString[idx]代表字符可以是在模式串的哪些位置
    14     }
    15 
    16     return hash;
    17 }
    18 
    19 //the patternString length must be less than 64
    20 MatchingInfo * ShiftAnd(char *patternString, char *dataString, unsigned int dsLen)
    21 {
    22     unsigned int idxDs = 0, psLen = strlen(patternString);
    23     long long *hash = initAlphbat(patternString);
    24 
    25     long long prefix = 0;  //每一位表示一个模式串的前缀,如果该位是1则表示当前该前缀被匹配上
    26 
    27     if(hash == NULL) return NULL;
    28 
    29     //匹配信息的初始化
    30     MatchingInfo *mi = (MatchingInfo *)malloc(sizeof(MatchingInfo));
    31     if(mi == NULL) return NULL;
    32     mi->indexOfMatch = (unsigned int *)malloc(sizeof(unsigned int));
    33     mi->numOfMatch = 0;
    34     mi->allocLen = 1;
    35 
    36     //下面的循环中动态更新prefix
    37     for(idxDs = 0; idxDs < dsLen; ++idxDs)
    38     {
    39         prefix = (prefix << 1) | 1;
    40         prefix &= hash[(unsigned int)dataString[idxDs]];
    41         if(prefix & ((long long)1 << (psLen - 1)))
    42         {
    43             //匹配上一个模式串
    44             if(mi->allocLen > mi->numOfMatch)
    45             {
    46                 //记录下标的内存够用
    47                 mi->indexOfMatch[mi->numOfMatch++] = idxDs - psLen + 1;
    48             }
    49             else
    50             {
    51                 //扩张匹配下标的内存
    52                 mi->indexOfMatch = (unsigned int *)realloc(mi->indexOfMatch, (mi->allocLen << 1) * sizeof(unsigned int));
    53                 mi->allocLen <<= 1;
    54                 mi->indexOfMatch[mi->numOfMatch++] = idxDs - psLen + 1;
    55             }
    56         }
    57     }
    58 
    59     free(hash);
    60     hash = NULL;
    61     return mi;
    62 }
  • 相关阅读:
    存储过程中执行动态Sql语句
    模拟alert和confirm
    SignalR
    Html5实践之EventSource
    Java路径操作具体解释
    HDU 1330 Nearest Common Ancestors(求两个点的近期公共祖先)
    Graph(2014辽宁ACM省赛)
    基于注解的Spring MVC整合Hibernate(所需jar包,spring和Hibernate整合配置,springMVC配置,重定向,批量删除)
    W5500问题集锦(二)
    Android Fragment 简单实例
  • 原文地址:https://www.cnblogs.com/ACystalMoon/p/2839293.html
Copyright © 2011-2022 走看看