Кратчайшие однозначно определяющие подстроки


23

При наличии списка строк замените каждую строку одной из ее непустых подстрок, которая не является подстрокой ни одной из других строк в списке, и настолько короткой, насколько это возможно.

пример

Учитывая список ["hello","hallo","hola"], "hello"должен быть заменен так же, "e"как эта подстрока не содержится в "hallo"и "hola"и это как можно короче. "hallo"может быть заменен либо "ha"или "al"и "hola"любой из "ho", "ol"или "la".

правила

  • Вы можете предположить, что строки будут непустыми и содержат только алфавитные символы одного и того же регистра.
  • Можно предположить, что такая подстрока существует для каждой строки в списке, т.е. ни одна строка в списке не будет подстрокой любой из других строк.
  • Ввод и вывод могут быть в любом разумном формате.
  • Это , поэтому старайтесь использовать как можно меньше байтов на выбранном вами языке.

Тестовые случаи

В большинстве случаев дается только один возможный вывод.

["ppcg"] -> ["p"] (or ["c"] or ["g"])
["hello","hallo","hola"] -> ["e","ha","ho"]
["abc","bca","bac"] -> ["ab","ca","ba"]
["abc","abd","dbc"] -> ["abc","bd","db"]
["lorem","ipsum","dolor","sit","amet"] -> ["re","p","d","si","a"]
["abc","acb","bac","bca","cab","cba"] -> ["abc","acb","bac","bca","cab","cba"]

Связанный: Кратчайшая Идентифицирующая Подстрока - похожая идея, но более сложные правила и громоздкий формат.


Почему не ""(пустая строка) однозначно идентифицирует для одного "ppcg"случая?
MooseBoys

2
@MooseBoys Учитывая список строк, замените каждую строку одной из ее непустых подстрок
Mr. Xcoder

Ответы:




4

Pyth , 12 байт

mhf!ts}LTQ.:

Попробуй это здесь!

Как это работает

В основном фильтрует подстроки каждой из них, которые встречаются только в одной из строк в списке (то есть она уникальна для этой строки), и получает первую.

mhf!ts}LTQ.:     Full program, Q=eval(stdin_input())
m         .:     Map over Q and obtain all the substrings of each.
  f              And filter-keep those that satisfy (var: T)...
      }LTQ       ... For each string in Q, yield 1 if it contains T, else 0.
   !ts           ... Sum the list, decrement and negate. 
 h               Head. Yields the first valid substring, which is always the shortest.

4

Пролог (SWI) , 175 163 байта

S/L/R:-sub_string(S,_,L,_,R).
[H|T]+[I|R]:-string_length(H,L),between(1,L,X),H/X/I,T+R.
R+R.
L-R:-L+R,forall(member(E,L),findall(_,(member(F,R),\+ \+ E/_/F),[_])).

Попробуйте онлайн!

Большинство вещей здесь должно быть довольно очевидным, но:

объяснение

Подписи: ( += вход, ?= необязательно, -= выход, := выражение)

  • sub_string(+String, ?Before, ?Length, ?After, ?SubString)
  • string_length(+String, -Length)
  • member(?Elem, ?List)
  • between(+Low, +High, ?Value)
  • findall(+Template, :Goal, -Bag)
  • forall(:Cond, :Action)

\+ \+просто not not(т.е. преобразует совпадение в логическое значение (в этом случае предотвращает сопоставление обоих ps по ppcgотдельности))


Подходящий инструмент для работы: P за исключением того факта, что это невероятно многословно
только ASCII


4

J , 30 29 25 байт

1(|:(0{-.&,)"_1]\.)<\\.&>

Попробуйте онлайн!

                   <\\.&>        a 3-dimensional array of substrings
1 |:                             transpose each matrix to sort the substrings by length
1              ]\.               all choices where one word is missing
    (0{-.&,)"_1                  for every matrix, flatten, remove substrings
                                  that are present in the corresponding complement,
                                  pick first


3

JavaScript (ES6), 93 байта

a=>a.map(s=>(L=s.length,g=n=>a.every(S=>S==s|!~S.search(u=s.substr(n%L,n/L+1)))?u:g(n+1))(0))

Попробуйте онлайн!

Как?

Для каждой строки s длины L во входном массиве a [] и начиная с n = 0 , мы используем рекурсивную функцию g () для генерации всех подстрок u из s с помощью:

u = s.substr(n % L, n / L + 1)

Например, с s = "abc" и L = 3 :

 n | n%L | floor(n/L+1) | u
---+-----+--------------+-------
 0 |  0  |       1      | "a"
 1 |  1  |       1      | "b"
 2 |  2  |       1      | "c"
 3 |  0  |       2      | "ab"
 4 |  1  |       2      | "bc"
 5 |  2  |       2      | "c"
 6 |  0  |       3      | "abc"
 7 |  1  |       3      | "bc"
 8 |  2  |       3      | "c"

Некоторые подстроки генерируются несколько раз, но это не имеет значения. Важно то, что все подстроки длины N были сгенерированы перед любой подстрокой длины N + 1 .

Мы остановить процесс , как только у не может быть найдено в любой другой строки S в а [] , который гарантированно произойдет , когда у == S в худшем случае, как правило , на вызов # 2:

ни одна строка в списке не будет подстрокой любой из других строк

Следовательно, в приведенном выше примере этапы 7 и 8 фактически никогда не будут обработаны.


2

PowerShell , 107 байт

($a=$args)|%{$(for($i=0;$i++-lt($g=($s=$_)|% Le*)){0..($g-$i)|%{$s|% s*g $_ $i}|?{!($a-match$_-ne$s)}})[0]}

Попробуйте онлайн!

объяснение

Для каждой предоставленной строки (и назначить весь массив $a):

  • Выполните forцикл по каждой длине подстроки (на основе 1) строки (назначая саму строку $sи длину $g)
  • Для каждой длины ( $i):
    • Создайте цикл индекса от 0 до длины - $i, затем для каждого индекса:
      • Получить подстроку текущей строки ( $s) в позиции $_(индекс) и длины$i
      • Передайте эту подстроку Where-Object( ?) и верните ее, если:
        • Подмножество array ( $a), которое не содержит текущей строки $s, не соответствует текущей подстроке$_

Вернемся к строковому уровню, у нас есть все подстроки этой строки, которые не были найдены в других, поэтому возьмите первую, [0]поскольку нам нужна только одна из них, затем перейдите к следующей строке.


0

C # (интерактивный компилятор Visual C #) , 149 байт

a=>a.Select(s=>{var t=s;for(int j=0,k,l=s.Length;j++<l;)for(k=-1;j+k++<l;)if(!a.Where(u=>s!=u&u.Contains(t=s.Substring(k,j))).Any())j=k=l;return t;})

Попробуйте онлайн!

Менее гольф ...

// a is an input array of strings
a=>
  // iterate over input array   
  a.Select(s=>{
    // t is the result string
    var t=s;
    // j is the substring length
    for(int j=0,k,l=s.Length;j++<l;)
      // k is the start index
      for(k=-1;j+k++<l;)
        // LINQ query to check if substring is valid
        // the tested string is collected in t
        if(!a.Where(u=>s!=u&u.Contains(t=s.Substring(k,j))).Any())
          // break loops
          j=k=l;
    // return result
    return t;
  })
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.