Я пытаюсь найти минимальное расстояние между несколькими словами в данном тексте.
Предположим, что у меня есть строка, такая как: " a b собака-кошка x y z n m p-лиса x собака b b кошка "
Найти минимальное расстояние всех совпадений подстрок: (лиса, собака, кошка)
есть несколько вхождений каждой подстроки в этом тексте:
кошка - 4
собака - 8
лиса - 24
dist = 24 - 4 = 20
лиса - 24
собака - 30
кот - 38
dist = 38 - 24 = 14
мин. Расст = 14
Вот алгоритм, который я придумал:
object MinKWindowSum {
def main(args: Array[String]): Unit = {
val document =
"""This Hello World is a huge text with thousands
Java of Hello words and Scala other lines and World and many other Hello docs
Words of World in many langs Hello and features
Java Scala AXVX TXZX ASDQWE OWEQ World asb eere qwerer
asdasd Scala Java Hello docs World KLKM NWQEW ZXCASD OPOOIK Scala ASDSA
"""
println(getMinWindowSize(document, "Hello World Scala"))
}
def getMinWindowSize(str:String, s:String): Int = {
/* creates a list of tuples List[(String, Int)] which contains each keyword and its
respective index found in the text sorted in order by index.
*/
val keywords = s.split(" ").toSet
val idxs = keywords.map(k => (k -> ("(?i)\\Q" + k + "\\E").r.findAllMatchIn(str).map(_.start)))
.map{ case (keyword,itr) => itr.map((keyword, _))}
.flatMap(identity).toSeq
.sortBy(_._2)
// Calculates the min window on the next step.
var min = Int.MaxValue
var minI, minJ = -1
// current window indexes and words
var currIdxs = ListBuffer[Int]()
var currWords = ListBuffer[String]()
for(idx <- idxs ) {
// check if word exists in window already
val idxOfWord = currWords.indexOf(idx._1)
if (!currWords.isEmpty && idxOfWord != -1) {
currWords = currWords.drop(idxOfWord + 1)
currIdxs = currIdxs.drop(idxOfWord + 1)
}
currWords += idx._1
currIdxs += idx._2
// if all keys are present check if it is new min window
if (keywords.size == currWords.length) {
val currMin = Math.abs(currIdxs.last - currIdxs.head)
if (min > currMin) {
min = currMin
minI = currIdxs.head
minJ = currIdxs.last
}
}
}
println("min = " + min + " ,i = " + minI + " j = " + minJ)
min
}
}
В приведенном выше примере мы пытаемся найти минимальное расстояние между всеми совпадениями «Hello World Scala»
Самое короткое окно между индексами найдено между индексами:
i = 235, j = 257 -> min = 22 * 1037 *
Интересно, есть ли лучший способ сделать это идиоматическим способом или лучше с точки зрения эффективности, масштабируемости, читабельности и простоты?