我有一个大数组有近10000个字符串,我想在这些字符串中找到所有公共部分(长度超过3个字符)并得到这些部分的出现。
我使用我的简单方法用javascript实现,但它确实花了很多时间,即使我做了一些优化,对于1000个字符串的短数组,Firefox的成本约为8s,Chrome的成本约为12。
所以我想知道是否有任何相关的技术或算法,因为我认为这是一个常见的问题,可以在许多应用程序中提出。
答案 0 :(得分:1)
构建一个包含所有可能子串的数组,对它们进行排序,然后查找连续相等字符串的块。
下面的实现查找一定长度的后缀并强加最少数量的匹配。目前尚不清楚你想要什么,但你需要一些约束。很容易找到最长的常见后缀,但如果你只是想要常见的后缀,这是什么意思?是否出现了4个字符串的20个出现比10个出现的5个字符串更好?
另请注意,下面的代码不会检查重叠的字符串。如果您查找长度为4的匹配项并且其中包含"green"
的30个字词,则结果将同时包含"gree"
和"reen"
。
它可能不是你想要的,但应该很容易适应。它的速度相当快。在10,000个随机生成的字符串中,每个字符串大约有30个字符,找到长度为10的公共子字符串需要不到一秒钟,对于1000,000个字符串,可能需要4秒。
无论如何,这里是:
/*
* Return an array of all substrings of the given length
* that occur at least mincount times in all the strings in
* the input array strings.
*/
function substrings(strings, length, mincount) {
var suffix = [];
var res = [];
for (var i = 0; i < strings.length; i++) {
var s = strings[i];
for (var j = 0; j < s.length - length + 1; j++) {
suffix.push(s.substr(j, length));
}
}
suffix.sort();
suffix.push("");
var last = "";
var count = 1;
for (var i = 0; i < suffix.length; i++) {
var s = suffix[i];
if (s == last) {
count++;
} else {
if (count >= mincount) res.push(last);
count = 1;
}
last = s;
}
return res;
}
答案 1 :(得分:0)
查看Crossfilter http://square.github.io/crossfilter/它将执行您想要的任何类型的地图缩减。但是,通过大混乱搜索Javascript可能会非常缓慢。根据你的约束条件,以及10,000个字符串将如何随着时间的推移而增长,你可能会想到一个RDMS,比如MySQL,因为它们是为这类事物而设计的。
答案 2 :(得分:0)
我遇到了一个稍有不同的问题,我需要找到每个单词的通用前缀,而不仅仅是单词中间或结尾的通用子字符串。此函数将返回一组单词的公共前缀。
function findCommonPrefixes (words, min) {
const result = new Set();
for (const word of words) {
let partial = word.toLowerCase();
do {
const otherWords = words.filter(w => w !== word).map(w => w.toLowerCase());
for (const word of otherWords) {
if (word.includes(partial)) {
result.add(partial);
partial = '';
break;
}
}
if (partial) {
partial = partial.slice(0, (partial.length - 1))
}
} while (partial.length && partial.length >= min)
}
return Array.from(result);
}