用于测量在两个字符串中出现的大小> = 2的子序列的数量的度量

时间:2017-01-20 13:37:30

标签: string algorithm dynamic-programming

假设我有2个相等长度的字符串。我正在寻找一个度量来衡量两个字符串在它们都具有大小> = 2的子序列数量方面密切相关的程度。

例如,假设x="ABCDEF"y="DEFABC"。在这两个字符串中,子序列"ABC""DEF""AB""BC""DE""EF"都是内部子序列{ {1}}并出现在两个字符串中。

是否有任何度量标准或非天真算法可以衡量这些模式中有多少出现在两个字符串中?

2 个答案:

答案 0 :(得分:2)

您可以尝试使用后缀树 / 后缀数组

https://en.wikipedia.org/wiki/Suffix_array

https://en.wikipedia.org/wiki/Suffix_tree

对于后缀数组实现中问题中提供的示例,您将拥有

ABCDEF -> $  
          ABCDEF$
          BCDEF$
          CDEF$
          DEF$
          EF$
          F$

($ marks end of string)

后缀数组,允许您将二进制搜索用于其他字符串 n-gram 。让我们在后缀数组上测试"DEFABC"的n-gram:

 "DE"   - found (DEF$), countinue to longer n-gram (3-gram)
 "DEF"  - found (DEF$), countinue to longer n-gram (4-gram)
 "DEFA" - failed, continue to next 2-gram
 "EF"   - found (EF$), countinue to longer n-gram (3-gram) 
 "EFA"  - failed, continue to next 2-gram
 "FA"   - failed, continue to next 2-gram
 "AB"   - found (ABCDEF$), countinue to longer n-gram (3-gram)
 "ABC"  - found (ABCDEF$), end of string reached, continue to next 2-gram
 "BC"   - found (BCDEF$), end of string reached
找到

6常见 n-gram n >= 2)。

到目前为止,我们花了N来创建后缀数组O(N*log(N))来扫描 n-gram O(N*log(N))扫描,O(N)查看后缀数组); 后缀树更难实现,只需创建O(log(N))即可。

一般情况下,检查大小为O(N)M的字符串时,如果后缀数组和{{1},则复杂度为N后缀树的情况下。

示例 C#代码

O(M*log(M) + N*log(M))

答案 1 :(得分:1)

有简单的O(n ^ 3)解决方案,首先为每个字符串提取所有序列并使用3个嵌套循环i(1..n)j(1..i)k存储它们(例如在地图内) (j..i)并确保每个序列的长度> = 2,现在迭代2个存储的序列并计算发生的数量。

<强> UPD

这是一个伪Java代码:

        char[] s1 = next().toCharArray();
        HashMap<String,Integer> map1 = new HashMap<>();
        for(int i=0;i<s1.length;i++)
            for(int j=0;j<=i;j++)
                if(i-j>=2) {
                    String sub = "";
                    for(int k=j;k<=i;k++)
                        sub+=s1[k]; // Instead use String builder to concat 2 strings because concating using String class in Java is O(n)
                    if(map1.get(sub) == null)
                        map1.put(sub,0);
                    map1.put(sub,map1.get(sub)+1);

                }
        for(String sub:map1.keySet())
            out.println(sub + " " +map1.get(sub));

对2字符串执行相同操作并计算发生的次数。