繁体   English   中英

如何计算从列表L(所有子串的列表)中选择k个相等子串的方式的数量

[英]How to count the number of ways of choosing of k equal substrings from a List L(the list of All Substrings)

给定由N个小写英文字母组成的字符串S

假设我们有一个列表L ,该列表L由字符串S的所有非空子字符串组成。

我需要计算从列表L完全选择K相等字符串的方法的数量(请注意,子字符串的长度不必等于k )。 1≤N≤5000 1≤K≤10 ^ 9

范例:

Let S=ababa. 

As List L = {"a", "b", "a", "b", "a", "ab", "ba", "ab", "ba", "aba", "bab", "aba", "abab", "baba", "ababa"}

let k=2

方式数为7:

("a", "a")
("a", "a") 
("a", "a") 
("b", "b") 
("ab", "ab") 
("ba", "ba") 
("aba", "aba")

类似地:

let k=3

否的方法将是1:

("a", "a", "a")

“所有子字符串的列表”。 为什么会有所有子串的列表? 假设您有一百万个字符的字符串,其中有五千亿个子字符串。 解决问题根本不需要所有子字符串的列表。

如果K = 0,则只有一种方法。 如果K = 1,则有N种方法。

对于k = 1到N,每个长度为k的子串可以从0到N-k的索引处开始,即N-k +1个子串。 使用哈希表确定不同的字符串并计算每个字符串有多少个。 然后对于出现n次的每个不同字符串,n> = k,将(n乘以K)添加到您的计数中。

而已。

通过先查看长度为1的字符串,忽略所有少于K个相等字符串的字符串,计算方式数,然后向每个方式添加另一个字符并重复,可以更快地做到这一点。 假设K = 5,您在字符串中有一百万个字符,并且只有两个长度为6的子字符串出现了五次或更多次,那么您只需要向这两个子字符串中添加字符。

为给定的字符串构建后缀数组

遍历此数组,查找(至少k个)邻居后缀的常见起始符号。

这是JavaScript中的一些内容:

function choose(n,k){
 if(k>n)return 0;if(k==0||n==k)return 1;var p=n;for(var i=2;i<=k;i++)p*=(n+1-i)/i;return p;
}

function f(str,k){
  var n = str.length,
      h = {},
      count = 0;

  for (var i=0; i<n; i++){
    var s = "";
    for (var j=i; k <= n - j + i && j < n; j++){
      s += str.charAt(j);
      if (h[s])
        h[s]++;
      else
        h[s] = 1;
    }
  }

  for (var i in h)
    count += choose(h[i],k);

  return count;
}

输出:

console.log(f("ababa",2));
console.log(f("ababa",3));

7
1

正如其他人所注意到的,您实际上并不需要子字符串列表。 因为您只关心相等的子字符串,所以您只需要计算一个子字符串出现的次数,就可以使用哈希/字典/映射进行跟踪。 那么,当子串出现n次时,选择恰好k相等的子串的方法的数量就是二项式系数c(n,k) 您可以为每个不同的子字符串加总所有这些二项式系数,然后您便有了答案。

请注意,如果您向这个问题询问多个k值,则只需构建一次哈希/字典/映射。

没有关于您正在学习的语言的任何详细信息,我相信您可以通过一个简单的嵌套循环来完成。 只需将每个值与数组或列表中的所有值进行比较即可。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM