String 查找字符串对

String 查找字符串对,string,algorithm,linear-search,String,Algorithm,Linear Search,我试着练习一些基于字符串和算法的问题,我偶然发现了一个问题,其措辞如下: 您有一个长度为N的字符串x,它由英文小字母组成。必须找到x中的子字符串s的数目,以便>0 >条件>代码> x[a]=x[c]和x[b]=x[d] < /c>是真的,我们需要考虑两种情况: One是当x[a]==x[b]即相同字符重复4次或更多次时,我们称这种情况为相似性,为了处理这种情况,我们创建一个结构来存储字符及其频繁性,然后当其频繁性>=4时,我们就有了我们正在寻找的模式。您可以在下面看到,它在代码中单独处理。可能组

我试着练习一些基于字符串和算法的问题,我偶然发现了一个问题,其措辞如下:


您有一个长度为N的字符串x,它由英文小字母组成。必须找到x中的子字符串s的数目,以便<代码>>0 >条件>代码> x[a]=x[c]和x[b]=x[d] < /c>是真的,我们需要考虑两种情况:

One是当
x[a]==x[b]
即相同字符重复4次或更多次时,我们称这种情况为相似性,为了处理这种情况,我们创建一个结构来存储字符及其频繁性,然后当其频繁性>=4时,我们就有了我们正在寻找的模式。您可以在下面看到,它在代码中单独处理。可能组合的数量可使用以下公式进行数学计算:

C(n,r)=n!/((n−r)!r!) // r=4 here, and n is the frequency of the character.
我们对所有相似性进行计算,并将一些添加到非相似性导致的总数中

另一种情况是查找两个不同的字符
x[a]!=x[b]

X="arbsatbuavb"    Then n=3 (a after b 3 times); S=n(n-1)/2=3  
X="arbsatbuavbwaxb" Then n=4; S=n(n-1)/2=6
在这里,我们需要解析数组并查找两个字符的每一次不同出现,将它们作为字典结构的键
,其中
表示a之后
b出现的次数(但a之后不再计算b)
,然后,对于结构中的每个键,我们使用以下数学方法获得满足条件的非相似性出现的子字符串总数:

S=

以下是实施的算法及其结果:

public static void main(String[] args) {
    System.out.println("TOTAL S ="+ calculate("aaaaa"));
}

public static int calculate(String str) {
    int s = 0;
    Map<String, Integer> struct = new HashMap<String, Integer>();
    Map<String, String> indexes = new HashMap<String, String>();
    Map<String, String> similarities = new HashMap<String, String>();
    String[] x = str.split("(?!^)");// convert the string to array.

    //Handle similarities
    for (int i = 0; i < x.length; i++) {
        if (similarities.containsKey(x[i])) {
            similarities.put(x[i], similarities.get(x[i]) + "," + i); // "a": 1,3,7...
        } else {
            similarities.put(x[i], i + "");
        }
    }

    //Ignore similarities
    ArrayList<String> temp = new ArrayList<String>();
    for (int i = 0; i < x.length - 1; i++) {
        temp.clear();// this temp is important otherwise "cdxd" will count
                        // "cd" twice!!!
        for (int j = i + 1; j < x.length; j++) {
            if (!x[i].equals(x[j])) {// for example if "abcdamn" when reach the second a stop j and jump to the next i.
                if (struct.containsKey(x[i] + x[j])) { // NOTE x[i] + x[j] is a String
                    if (!temp.contains(x[j])) {


                        struct.put(x[i] + x[j], struct.get(x[i] + x[j]) + 1);
                        temp.add(x[j]);

                        //Update
                        indexes.put(x[i] + x[j],indexes.get(x[i] + x[j])+ ";"+i+","+j);

                    }
                }

                //UP I have excluded similarities ie. if we have the following "aaaaa" then we have c(5,4) =

                else {

                    struct.put(x[i] + x[j], 1); // NOTE x[i] + x[j] is a String
                    temp.add(x[j]);

                    //Update
                    indexes.put(x[i] + x[j], i+","+j);
                }
            } else {
              break;
            }
        }
    }
    // now compute the result when similarities ignored
    for (Map.Entry<String, Integer> entry : struct.entrySet()) {
        s += entry.getValue() * (entry.getValue() - 1) / 2;
    }


    //Update
    //calculating s taking similarities into account
    int simil=0;
    ArrayList<String> perm=new ArrayList<String>();
    System.out.println("String pairs of '"+str+"' :");
    System.out.println("Similarities ie.(aaaaa)");
    for (Map.Entry<String, String> entry : similarities.entrySet()) {
        if(entry.getValue().split(",").length>=4)
        {
            String[] indxsim=entry.getValue().split(",");
            simil+=factorial(indxsim.length)/(factorial(indxsim.length-4)*factorial(4));/*C(n,r)=n!/(n−r)!r!*/

          //show similarities results:12345=>1234;1235;1245;1345;2345
            for(int i=0;i<indxsim.length-3;i++)
                for(int j=i+1;j<indxsim.length-2;j++)
                    for(int k=j+1;k<indxsim.length-1;k++)
                        for(int l=k+1;l<indxsim.length;l++)
                        {
                            if(!perm.contains(indxsim[i]+indxsim[j]+indxsim[k]+indxsim[l]))//indxsim[i] is String
                            {
                                perm.add(indxsim[i]+indxsim[j]+indxsim[k]+indxsim[l]);
                                System.out.println(indxsim[i]+indxsim[j]+indxsim[k]+indxsim[l]);
                            }
                        }
        }
    }
    //show results by parsing indexes and calculating sub strings
    System.out.println("NON-Similarities (cd*cd*)");

    for (Map.Entry<String, String> entry : indexes.entrySet()) {
        if(entry.getValue().split(",").length>2)
        {
            String[] indx=entry.getValue().split(";");
            for (int i=0;i<indx.length-1;i++)
                for(int j=i+1;j<indx.length;j++)
                {
                    System.out.println(indx[i]+","+indx[j]);
                }
        }
    }
    s+=simil;
    return s;
}

  public static int factorial(int n) {
        if (n == 0) {
            return 1;
        }
        int fact = 1; // this  will be the result
        for (int i = 1; i <= n; i++) {
            fact *= i;
        }
        return fact;
    }
根据评论更新

注意。

提示:如果
f(a)
返回
ab
组合的数量(包括
a
),则:

f(next-a-to-the-left) = 
  f(a) + count of b's to the right
         of next-a-to-the-left
对于每个
b
,都有

f(next-a-to-the-right) * count of a's to the left

有效组合。

子字符串S是如何由a、b、c和d定义的?询问满足此条件的元组(a,b,c,d)的可能值的个数更有意义。或者
a,b,c,d
是后续索引?它们不必是对等索引。它们可能是但不是必需的。因此
子字符串
术语不正确-它是子字符串。如果您要共享源代码,您帖子中的措辞会非常混乱。在这样的示例中,
ababababab
(索引1到7),你的想法会计算像1-4-5-6或2-3-4-7这样的组合吗?@我已经更新显示了我们正在寻找的字符串对。你计算的“ab”对似乎都是连续的,但如果中间有其他“a”或“b”,比如我上面评论中的例子,那么有效的组合又如何呢?OP规定a、b、c、d是有序的,但不是连续的(例如,意味着在“a”和“c”之间可能有另一个“a”类型)。让我们以您自己的例子,
“ababababab”的字符串对
。您没有列出有效组合的
0-3-4-5
。@您是对的!,我在更新中加入了相似性处理,谢谢。
f(next-a-to-the-right) * count of a's to the left