【问题标题】:Find string pairs查找字符串对
【发布时间】:2017-11-14 09:05:59
【问题描述】:

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

你有一个长度为 N 的字符串 x,它由小英文字母组成。您必须在 x 中找到子字符串 S 的数量,例如 0 <= d < c < b < a <= N - 1x[a] == x[c] and x[b] == x[d]

例如: x = "ababa" 答案是s=2,因为有两个字符串满足上述条件: ababbaba.

解决这个问题的最佳方法是什么?

提前致谢。

【问题讨论】:

  • a,b,c,d如何定义子串S?询问满足此条件的元组 (a,b,c,d) 的可能值的数量更有意义。
  • a,b,c,d 是后续索引?
  • 它们不必是连续索引。它们可以但不是必需的。
  • 所以substring这个词是不对的——它是子序列
  • 能否请您分享出处,您帖子中的措辞非常混乱。

标签: string algorithm linear-search


【解决方案1】:

提示:如果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

有效的组合。

【讨论】:

    【解决方案2】:

    要使x[a] == x[c] and x[b] == x[d] 为真,我们需要考虑两种情况:

    一个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
    

    在这里,我们需要解析数组并查找两个字符的每个不同出现,将它们作为字典结构<key,value> 的键,其中value 表示b after a (but no more Bs counted for that a) 的出现次数,然后是每个键在结构中,我们使用以下数学方法来获得满足条件的非相似性出现的子字符串的总数:

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

    结果: 直接取自程序的输出。 __ 索引是从零开始的!

        String pairs of 'abababa' :
    Similarities ie.(aaaaa)
    0246
    NON-Similarities (cd*cd*)
    0,1,2,3
    0,1,4,5
    2,3,4,5
    1,2,3,4
    1,2,5,6
    3,4,5,6
    TOTAL S =7
    
    
    
        String pairs of 'www.google.com' :
    Similarities ie.(aaaaa)
    NON-Similarities (cd*cd*)
    3,5,10,12
    4,5,7,12
    TOTAL S =2
    
    
    
     String pairs of 'hellothisisarandomtext' :
    Similarities ie.(aaaaa)
    NON-Similarities (cd*cd*)
    0,4,6,16
    0,5,6,18
    7,8,9,10
    1,5,19,21
    4,5,16,18
    0,1,6,19
    TOTAL S =6
    
    
    
    
    
    
     String pairs of 'ababaaa' :
    Similarities ie.(aaaaa)
    0245
    0246
    0256
    0456
    2456
    NON-Similarities (cd*cd*)
    0,1,2,3
    1,2,3,4
    TOTAL S =7
    

    根据评论更新

    问候。

    【讨论】:

    • 在这样的示例中,abababa(索引 1 到 7),您的想法是否计算 1-4-5-6 或 2-3-4-7 之类的组合?
    • @גלעדברקן 我已更新显示我们正在寻找的字符串对。
    • 您计算的“ab”对似乎都是连续的,但是如果有效组合之间有其他“a”或“b”,例如我评论中的示例多于? OP 规定 a,b,c,d 是有序的,但不是连续的(例如,“a”和“c”之间可能有另一个“a”类型)
    • 让我们举个例子,"String pairs of 'abababa"。您没有列出0-3-4-5,这是一个有效的组合。
    • @גלעדברקן 你说得对!我在更新中包含了相似性处理,谢谢。
    猜你喜欢
    • 1970-01-01
    • 2020-09-26
    • 2012-09-07
    • 2011-01-11
    • 2013-10-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多