频繁从一堆 string 里查找特定前缀的字符串,大家有什么快速算法吗? - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
kongque2016
V2EX    编程

频繁从一堆string 里查找特定前缀的字符串,大家有什么快速算法吗?

  •  
  •   kongque2016 2018-07-15 21:03:41 +08:00 4582 次点击
    这是一个创建于 2713 天前的主题,其中的信息可能已经有所发展或是发生改变。
    或者说,现在有一堆字符串(数量约 1000 ),随意给定前几个字符,例如"abc",要求找出所有以"abc"开头的字符串。
    要实现成一个函数,因为调用的频繁,所以要考虑性能。
    具体应用场合大家可以回想 vim 状态栏按冒号然后上 /下翻找历史命令时,它会根据已输入的补全。
    我目前想到两个方法,方法一:
    把这些字符串排序存储。例如排序成这样:
    abc
    abcd
    bcd
    bce
    bceaaa
    begggggg
    c
    df

    排序算法是:按首字母逐渐往后比较。
    查找方法是简单的线性查找
    再跟大家确认一下函数的功能,例如:
    接受"ab",要返回"abc", "abcd";
    接受“ bce",要返回"bce","bceaaa";


    方法二:
    设置 10 个哈希表,对所有字符串手动做 hash,从第一个字母开始,hash 算法每推进一个字符,就把当前的 hash 值存到对应的哈希表。
    这样,以后查找"abc"时,直接从第三个("abc"的 strlen 是 3)哈希表取出 hash 值对应"abc"的所有字符串,再做一下 strncmp()就行了。
    设置了 10 个哈希表,如果 10 个以后还区分不出,就另行存储,按方法 1 对待。

    各位有什么更好的,或更简单的方法,或者建议?希望能在这里交流一下。
    15 条回复    2018-08-24 08:12:08 +08:00
    F281M6Dh8DXpD1g2
        1
    F281M6Dh8DXpD1g2  
       2018-07-15 21:06:30 +08:00
    前缀树
    lhx2008
        2
    lhx2008  
       2018-07-15 21:08:45 +08:00 via Android
    楼上正解,或者直接丢进数据库建索引
    kongque2016
        3
    kongque2016  
    OP
       2018-07-15 21:10:14 +08:00
    @liprais @lhx2008
    如果用 C 语言实现的话,有什么好的方法?
    facat
        4
    facat  
       2018-07-15 21:10:59 +08:00
    正则表达式
    F281M6Dh8DXpD1g2
        5
    F281M6Dh8DXpD1g2  
       2018-07-15 21:12:24 +08:00
    @kongque2016 自己搜一下就行了,伸手党可耻
    haimall
        6
    haimall  
       2018-07-15 21:13:46 +8:00 via Android
    excel 有什么 loop 函数?
    yanaraika
        7
    yanaraika  
       2018-07-15 22:26:47 +08:00   1
    对于实际中不太长的字符串,方法 2 是最优的。前缀树空间太大
    wevsty
        8
    wevsty  
       2018-07-15 22:45:31 +08:00
    为什么我觉得根据你这种需求直接遍历查找是最快的。。。
    排序也好,求 HASH 也好,我都不觉得会比直接遍历查找更快。。
    MIMEIK
        9
    MIMEIK  
       2018-07-15 23:50:06 +08:00 via Android
    @wevsty 前缀短的话感觉直接比不错,比较长的前缀就有点尴尬了,看楼主的需求了。
    lance6716
        10
    lance6716  
       2018-07-15 23:54:09 +08:00 via Android
    此时就明白科班出身是多么重要了
    feverzsj
        11
    feverzsj  
       2018-07-16 00:01:29 +08:00
    数据量大的话,DAWG 是最快的
    zhujinliang
        12
    zhujinliang  
       2018-07-16 07:50:33 +08:00 via iPhone
    这种情形应该用什么心里没有 B 树吗?
    micean
        13
    micean  
       2018-07-16 08:54:05 +08:00
    1 楼 + 1
    feverzsj
        14
    feverzsj  
       2018-07-16 11:21:15 +08:00
    数据量中等的已排序序列,最快的方法是二分查找
    xuanbg
        15
    xuanbg  
       2018-08-24 08:12:08 +08:00
    看起来前缀数量有限,1 楼正解
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     2541 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 28ms UTC 12:40 PVG 20:40 LAX 04:40 JFK 07:40
    Do have faith in what you're doing.
    ubao msn snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86