[英]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.