zoukankan      html  css  js  c++  java
  • 字符串模式匹配——ShiftAnd和ShiftOR算法[转]

      Shift-And算法思想较之KMP算法很简单,设模式字符串为P,它主要通过保存一个集合DD中记录了P中所有与当前已读text的某个后缀相匹配的前缀),每当text有新的字符读入,算法利用位并行机制来更新这个集合D

      设P长度为m,则集合D可表示为D = dmd1 而用D[j]代表dj

      D[j]=1当且仅当p1…p是 t1…t的某个后缀,当D[m]=1时,就认为P已经于text匹配。

      当读入下一个字符 ti+1需要计算新的集合 D′. 当且仅当D[j]=1并且  ti+1 等于 pj+1D'[j+1]=1. 这是因为D[j]=1时有 p1…pj 是 t1…ti 的一个后缀,而当ti+1 等于 pj+1可推出p1…pj +1是 t1…ti+1 的一个后缀.这个集合可通过位运算来更新.

      算法首先建立一个数组B数组长度为text串所属字符集长度(例如A-Z的话数组B的长度为26.)  如果P的第j为等于c则将B[c中第j位置为1.

    因为要预处理计算B,如果字符集很大的话,并不划算。如果m很长的话(大于机器字长),也很不方便。所以这种算法适用于字符集较小,模式串小于机器字长的情况。当然对于模式串较长的情况,也是比brute force要快的,只是逻辑上要复杂些。


      Shift-And的代码如下,这里假设字符集的大小为128


    int shift_and(char * s, int len_s, char * p, int len_p)
    {
    int B[128];
    memset(B, 0, sizeof(B));

    int i;
    for (i=0; i<len_p; i++)
    B[p[i]] |= 1<<i;

    int D = 0;
    for (i=0; i<len_s; i++)
    {
    D = ((D<<1) | 1) & B[s[i]]; //D<<1与1位或操作,是可以让匹配随时从当前字符开始,使用位运算实现了并行
    if (D & (1<<(len_p-1)))
    return i - len_p+1;
    }
    return -1;
    }

    Shift-Or算法Shift-And算法思想是一样的,只是在通过取补,减少了位运算的次数,提高了速度。Shift-Or作的修改是,用零表示一个数在集合里,1表示不在,所以

    D = ((D<<1) | 1) & B[s[i]];

    修改为D=D<<1 | B[s[i]]; 省了一次位运算,当然BD的初始化的时候,也要作相应的修改。




    ====================================================================


    My Code:


    Shift-And



    int size = 128; // 此处默认字符集规模为128

    //预处理,
    void preShiftAnd(const char *p, int m, unsigned int *s){
    for(int i=0; i<size; i++)
    s[i] = 0;
    for(int i=0; i<m; i++){
    s[p[i]] |= 1<<i;
    }
    }

    //Shift—And
    int ShiftAnd(const char *t, const char *p){
    int tLen = strlen(t);
    int pLen = strlen(p);
    unsigned int state = 0; //即D数组
    unsigned int s[size];

    if(tLen < pLen) return -1;

    preShiftAnd(p, pLen, s); //预处理

    for(int i=0; i<tLen; i++){
    state = ((state<<1)|1) & s[t[i]];
    if(state & 1<<(pLen-1)) //最高位出现零
    return i - pLen + 1;
    }
    return -1;

    }



    Shift-Or


    #define WORDSIZE sizeof(int)*8 
    #define ASIZE 256 // 只考虑ASCII码字符集

    int preSo(const char *x, int m, unsigned int S[]) {
    unsigned int j, lim;
    int i;
    for (i = 0; i < ASIZE; ++i)
    S[i] = ~0; // 初值都是全1的二进制数
    for (lim = i = 0, j = 1; i < m; ++i, j <<= 1) {
    S[x[i]] &= ~j; // 当第 J 位为 I 的时候, S[I][J] = 0;
    lim |= j;
    }
    /*
    for (i = 0; i < m; i++) {
    cout << x[i] << " Feature " << bitset<sizeof(int)*8>( S[x[i]]) << endl;
    }
    */
    lim = ~(lim>>1);
    return(lim);
    }

    int SO(const char *x, int m, const char *y, int n) {
    unsigned int lim, state;
    unsigned int S[ASIZE];
    int j;
    if (m > WORDSIZE) {
    cout << "SO: Use pattern size <= word size";
    return -1;
    }

    /* Preprocessing */
    lim = preSo(x, m, S);

    /* Searching */
    for (state = ~0, j = 0; j < n; ++j) {
    state = (state<<1) | S[y[j]];
    if (state < lim)
    return j - m + 1;
    }
    return -1;
    }






  • 相关阅读:
    Python中的类(上)
    Django REST Framework API Guide 07
    Django REST Framework API Guide 06
    Django REST Framework API Guide 05
    Django REST Framework API Guide 04
    Django REST Framework API Guide 03
    Django REST Framework API Guide 02
    Django REST Framework API Guide 01
    Django 详解 信号Signal
    Django 详解 中间件Middleware
  • 原文地址:https://www.cnblogs.com/longdouhzt/p/2190550.html
Copyright © 2011-2022 走看看