【问题标题】:fast string check looking for in-string duplicates快速字符串检查寻找字符串内重复
【发布时间】:2012-03-03 20:07:48
【问题描述】:

string = "aabbccaaabbcbbdbabdaaa";
如何以有效的方式检查该字符串以查找内部字符串重复项:
我的意思是:

  1. string中寻找2个字母的字符串:

    aa = " aa bbcc aa abbcbbdbabd aa a";
    //这里没有空格或string 中的其他地方。只是添加它们以强调“aa”。
    aa = "aa bbcca aa bbcbbdbabda aa ";
    aa = 5;
    aa 之间的距离 = 4,5,11,12;

    bb = "aa bb ccaaa bb c bb dbabdaaa";
    总计 bb = 3;
    bb 之间的距离 = 5,1
    ...

  2. string 中寻找 3 个字母的字符串:

    aaa = " aaa bbcc aaa bbcbbdbabd aaa ";
    aaa = 3;
    aaa 之间的距离 = 4,10;
    ...


我的尝试是以 4 个周期的方式进行的,而且非常慢。

附言
任何帮助表示赞赏。对不起我的英语不好。

编辑:
抱歉问了不好的问题。我忘了说 string 还应该检查 4 个字符重复和其他字符重复:
aabb = " aabb cca aabb cbbdbabdaaa";
总计 aabb = 2;
aabb 之间的距离 = 3;


编辑 2:
我们正在寻找的重复项不应手动输入。假设string 是 20k 个符号,您正在搜索 ANY 重复项(没有空格)以及这些重复项之间的距离。
再次感谢并为不正确的问题再次道歉。

【问题讨论】:

标签: c# php javascript regex


【解决方案1】:

这是 C# 中的解决方案

static Dictionary<string, List<int>> GetDuplicates2(string value)
{
    var duplicates = new Dictionary<string, List<int>>();
    for (int i = 0; i < value.Length; i++)
    {
        for (int slength = 2; slength < (value.Length - i) / 2 + 2; slength++)
        {
            var littleString = value.Substring(i, slength);

            if (!duplicates.ContainsKey(littleString))
            {
                int nextOccurrence = value.IndexOf(littleString, i + slength - 1);

                if (nextOccurrence != -1)
                {
                    var l = new List<int>();
                    l.Add(i);
                    l.Add(nextOccurrence);
                    duplicates.Add(littleString, l);

                    while ((nextOccurrence = value.IndexOf(littleString, nextOccurrence + slength - 1)) != -1)
                    {
                        duplicates[littleString].Add(nextOccurrence);
                    }
                }
                else
                {
                    break;
                }
            }
            else
            {
                break;
            }
        }
    }

    return duplicates;
}

我是根据你的评论写的……

所有 [2, 3, ..., n/2] 个重复字符的列表,其中 n = 字符串 长度

我认为这工作得很好。它返回一个包含字符串和每个重复项的索引的字典。在性能方面,多次调用IndexOf() 可能是其中最慢的部分,但我不知道有什么办法。

更新 我更改了代码以包含重叠要求。

更新 #2 我添加了几个条件,其中算法将break 退出内部for 循环。这大大提高了性能(尤其是在找不到重复项的情况下)。

【讨论】:

  • 您的代码为输入 aabbccaaabbcbbdbabdaaa 返回 aa=3。它必须是 5
  • @L.B.啊,重叠的重复。直到你提到它,我才注意到这个要求。我刚刚更新了代码来解决这个问题。
  • 我是唯一一个满足 OP 的要求的人,即在不搜索任何特定内容的情况下查找所有重复项。然而我却被否决了……很好。
  • 为你投票,谢谢 :) 在选择“最”正确的答案之前,我会玩弄我的代码一段时间,如果可以这样调用的话。
  • @SteveWortham 我取消了我的反对票,但除非您编辑答案,否则它不会生效。
【解决方案2】:

有很多字符串搜索算法。

维基百科页面很好地总结了它们:

http://en.wikipedia.org/wiki/String_searching_algorithm

【讨论】:

    【解决方案3】:

    在 Javascript 中使用普通字符串函数。

    var a = " aa bbcc aa abbcbbdbabd aa a";
    var s = "aa", ix = [], i=0; 
    while(true){
        i = a.indexOf(s, i);
        if(i==-1)
           break;
        i += s.length
        ix.push(i);
    }
    

    现在ix 包含找到s (=aa) 的索引数组。 ix.length 是发现的总数。而下面的算法会发现两者之间的差异。

    var differences=[];
    for(var j=1; j<ix.length; j++){
        differences.push(ix[j]-ix[j-1]);
    } 
    

    这比正则表达式更快。

    【讨论】:

    • s 应该是:aa, ab, bb, bc, ...
      aab, abb, bbc, bcc, ...
      aabb, abbc, bbcc, ...
      等。抱歉,如果您误解了我的问题。我已经编辑过了。
    • @ted 是的,我知道我会告诉你怎么做。我不是为你做的。您可以遍历所有 aa、bb、cc 等并从我的代码中获取结果。
    • 嗯。我怎样才能循环通过a 所以s = aa; (然后:ab,bb,..aab,abb,..aabb,abbc,..aabbccaaabb)然后呢?谢谢你。上面的代码很棒(:
    【解决方案4】:

    这几乎与LZW compression algorithm 所做的完全一样,并且只需要通过字符串一次。

    【讨论】:

    • 出色的观察力。重叠的重复要求可能是最大的区别。除此之外,它非常相似。
    • 顺便说一句,我开始从 LZW 实现开始构建解决方案,但最终我发现了太多差异。最后,我想我开始重写上面的解决方案了。
    【解决方案5】:

    JavaScript。

        onclick = "f('a',3)"  //return 2
        onclick = "f('a',2)"  //return 5
        .......
        var f = function(ch, nb){  //ch - searching character. nb - number of repetitions
           var str = "aabbccaaabbcbbdbabdaaa";
           var strLen = str.length;
           var res = 0;
           for(var i = 0; i < strLen; ++i){
              if(str[i] == ch){
                 for(var j = i; j < nb+i || j <strLen; ++j){
                     if(str[j] != ch){
                     break;
                     }
                     if(j+1 == nb+i){
                     res++;
                     }
                 }
              }
          }
        return res;
    };
    

    【讨论】:

    • 对不起,我的回答不清楚。搜索字符及其重复次数应手动输入,因为字符串可以是 20k 符号,除 aabaas 之外,还应检查。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-08-18
    • 2020-12-09
    • 2017-05-12
    • 2017-06-09
    • 1970-01-01
    • 1970-01-01
    • 2014-05-09
    相关资源
    最近更新 更多