创建博客 登录  
 加关注
   显示下一条  |  关闭

(((silence)))

#define if(...) if(!(__VA_ARGS__))

 
 
 

日志

 
 

字符串匹配 ?  

2008-06-21 21:18:08|  分类: 编程 |  标签: |字号 订阅

传说kmp算法很伟大,但我更喜欢Shift-And算法:

template <class Output_Function>
size_t Shift_And(const char* source,const char* to_find,Output_Function out){
/**
 * find to_find in source, out(where_to_find_occured);
 * return the tatol occurence's account
 */
    size_t m=strlen(to_find);
    size_t occured=0;
    if (n<m) return 0;
    const int mask_len=m/64+1;
    const int last_section_len=m%64;

    __int64 mask[128][mask_len]; //如果你的编译器不支持VLA(变量长数组), 自己改改吧
    for(int i=0;i<mask_len;++i){
        for(int j=0;j<128;++j){
            mask[j][i]=0;
        }
    }
    for(size_t j=0;j<m;++j){
        mask[static_cast<int>(to_find[j])][j/64]|=1<<(j%64);
    }
    __int64 D[mask_len];
    for(int i=0;i<mask_len;++i){
        D[i]=0;
    }
    for(size_t pos=0;source[pos];++pos){
        for(int i=mask_len-1;i>=1;--i){
            D[i]<<=1;
            D[i]|=D[i-1]>>63;
            D[i]&=mask[static_cast<int>(to_find[pos])][i];
        }
        D[0]<<=1;
        D[0]|=1;
        D[0]&=mask[static_cast<int>(source[pos])][0];
        if (D[mask_len-1]>>(last_section_len-1)){
            out(pos-m+1);
            ++occured;
        }
    }
    return occured;
}

如果不想处理每个出现的地方, 只想知道指定字符串出现了几次, 最简单,不需要改动的方法是使用这个函数作为第三个参数:
void noop(...){
// No operation, may be useful for strange reasons
}

复杂度: 当需要查找的字符串长度在一个到几个机器字之间时, 查找一个或全部子串, 时间复杂度总是O(n).
而且这个算法是很容易扩展的, 比如在一个字符串里搜索多个子串, 忽略大小写, 等等等等, 懒得去做了.


  评论这张
转发至微博
转发至微博
0   分享到:        
阅读(145)| 评论(0)| 不可引用 |举报

历史上的今天

相关文章

最近读者

评论

<#--最新日志,群博日志--> <#--推荐日志--> <#--引用记录--> <#--博主推荐--> <#--随机阅读--> <#--首页推荐--> <#--相关文章--> <#--历史上的今天--> <#--右边模块结构--> <#--评论模块结构--> <#--引用模块结构--> <#--博主发起的投票-->
 
 
 
 
 
 
 
 
 
 
 
 
 
 

页脚

网易公司版权所有 ©1997-2012