快速字符串检查查找字符串中的重复项


fast string check looking for in-string duplicates

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

  1. string:
    中查找两个字母的字符串

    aa="aabbccaaabbcbdbabdaaa"
    //此处或string中的其他位置没有空白。只是添加它们来强调"aa"
    aa="aabbccaaabbcbbdbabdaaa"
    aa=5
    aa之间的距离=4,5,11,12

    bb="aabbccaaabbcbbdbabdaaa"
    合计bb=3
    bb之间的距离=5.1


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

    aaa="aaabbccaaabbcbbdbabdaaa"
    aaa=3
    aaa=4.10之间的距离


我的尝试是以4个循环的方式进行的,而且非常缓慢

p.S.
感谢您的帮助。对不起我的英语。

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


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

下面是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=string长度

我认为这很有效。它返回一个Dictionary,其中包含字符串和每个重复项的索引。就性能而言,多次调用IndexOf()可能是其中最慢的部分,但我对此一无所知。

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

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

有许多字符串搜索算法。

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

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

在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]);
} 

这比正则表达式更快。

这几乎正是LZW压缩算法所做的,它只需要对字符串进行一次遍历。

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;
};