Самая длинная неповторяющаяся подстрока


33

Задав строку в качестве входных данных, найдите самую длинную непрерывную подстроку, которая не имеет символов дважды или более. Если таких подстрок несколько, вы можете вывести либо. Вы можете предположить, что вход находится в диапазоне ASCII для печати, если хотите.

счет

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

тривиальность

В некоторых языках набрать 1, x (язык) или 2, x (брейк-бла и другие тьюрины) довольно легко, однако есть другие языки, в которых минимизация самой длинной неповторяющейся подстроки является проблемой. Мне было очень весело получить 2 балла в Haskell, поэтому я призываю вас искать языки, где это задание весело.

Контрольные примеры

"Good morning, Green orb!" -> "ing, Gre"
"fffffffffff" -> "f"
"oiiiiioiiii" -> "io", "oi"
"1234567890"  -> "1234567890"
"11122324455" -> "324"

Сдача баллов

Вы можете оценить свои программы, используя следующий фрагмент:


Предлагаемый контрольный пример: 11122324455Джонатан Аллан понял, что моя первая ревизия не справилась с этим правильно.
Деннис

@Dennis Тестовый кейс добавлен. Мне любопытно, как это случилось.
Пшеничный Волшебник

2
Я сгенерировал все подстроки (уже отсортированные по длине), затем дедуплицировал подстроки и сохранил те, которые остались подстроками. К сожалению, это меняет порядок; 11122происходит после 324, но дедуплицируется до 12.
Деннис

Мне интересно, где ответ пробела.
Волшебная Урна Осьминога

Ответы:


13

C, оценка 2,  747   720  662 байта

L  [  1  <<  7  ]  ,  *  q  ,  *  r  ,  l  ,  d  ,  i  ,  c  ,  j  ,  s  ,  t  ,  k  =  1  <<  7  ;  h  (  )  {  q  =  s  +  i  +  j  ++  ;  *  q  %  k  &&  !  L  [  *  q  %  k  ]  ++  &&  h  (  ++  c  )  ;  }  g  (  )  {  q  =  s  +  i  ;  *  q  %  k  ?  z  (  k  )  ,  h  (  j  =  c  =  0  )  ,  c  >  d  &&  (  d  =  c  )  &&  (  l  =  i  )  ,  g  (  ++  i  )  :  0  ;  }  f  (  S  ,  T  )  {  s  =  S  ;  l  =  i  =  d  =  0  ;  g  (  t  =  T  )  ;  p  (  i  =  0  )  ;  }  p  (  )  {  q  =  s  +  l  +  i  ;  r  =  t  +  i  ;  i  ++  <  d  ?  p  (  *  r  =  *  q  )  :  (  *  r  =  0  )  ;  }  z  (  i  )  {  L  [  --  i  ]  =  0  ;  i  &&  z  (  i  )  ;  }

Работает как минимум на 32-битном MinGW (с отключенной оптимизацией). Не использует ни одного ключевого слова.

Работает, видимо, на TIO с gcc и clang: попробуйте онлайн! (Спасибо @Dennis!)

Звоните с:

int main()
{
    char str[1024];

    f("Good morning, Green orb!", str);
    puts(str);

    f("fffffffffff", str);
    puts(str);

    f("oiiiiioiiii", str);
    puts(str);

    f("1234567890", str);
    puts(str);

    f("L  [  1  <<  7  ]  ,  *  q  ,  *  r  ,  l  ,  d  ,  i  ,  c  ,  j  ,  s  ,  t  ,  k  =  1  <<  7  ;  h  (  )  {  q  =  s  +  i  +  j  ++  ;  *  q  %  k  &&  !  L  [  *  q  %  k  ]  ++  &&  h  (  ++  c  )  ;  }  g  (  )  {  q  =  s  +  i  ;  *  q  %  k  ?  z  (  k  )  ,  h  (  j  =  c  =  0  )  ,  c  >  d  &&  (  d  =  c  )  &&  (  l  =  i  )  ,  g  (  ++  i  )  :  0  ;  }  f  (  S  ,  T  )  {  s  =  S  ;  l  =  i  =  d  =  0  ;  g  (  t  =  T  )  ;  p  (  i  =  0  )  ;  }  p  (  )  {  q  =  s  +  l  +  i  ;  r  =  t  +  i  ;  i  ++  <  d  ?  p  (  *  r  =  *  q  )  :  (  *  r  =  0  )  ;  }  z  (  i  )  {  L  [  --  i  ]  =  0  ;  i  &&  z  (  i  )  ;  }");
    puts(str);
}

Выход:

Код с чуть более читаемым форматированием:

L[1<<7],
*q, *r, l, d, i, c, j, s, t, k=1<<7;

h()
{
    q = s+i+j++;
    *q%k && !L[*q%k]++ && h(++c);
}

g()
{
    q = s+i;
    *q%k ? z(k), h(j=c=0), c>d && (d=c) && (l=i), g(++i) : 0;
}

f(S, T)
{
    s = S;
    l = i = d = 0;
    g(t=T);
    p(i=0);
}

p()
{
    q = s+l+i;
    r = t+i;
    i++<d ? p(*r=*q) : (*r=0);
}

z(i)
{
    L[--i] = 0;
    i && z(i);
}

И это можно использовать для генерации правильного интервала, чтобы перейти к форматированию со счетом 2: попробуйте онлайн!


C, оценка 3, 309 байт

i
,
j
,
l
,
c
,
d
;
f
(
\
c\
\
h\
\
a\
\
r
*
s
)
{
\
f\
\
o\
\
r
\
(
i
=
l
=
d
=
0
;
s
[
i
]
;
c
>
d
&&
(
d
=
c
)
&&
(
l
=
i
)
,
++
i
)
\
f\
\
o\
\
r
(
\
c\
\
h\
\
a\
\
r

L
[
\
1\
\
2\
\
8
\
]
=
{
j
=
c
=
0
}
;
s
[
i
+
j
]
&&
!
L
[
s
[
i
+
j
++
]
]
++
;
++
c
)
;
\
w\
\
r\
\
i\
\
t\
\
e
(
1
,
s
+
l
,
d
)
;
}

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


10

Haskell , оценка 2, 492 ... 307 224 212 209 207 байт

((yy:yyy))??ss|ss==yy  =  ""  |  yy==yy=yy:yyy??ss
ss??sss=ss
ss""=""

ss((ff:fff))  =  ff  :  ss  fff??ff
ff""=""

ff((xxx:xx))  =  ss((xxx:xx))##ff  xx
xx##xxx  |  ((((xx>>xx))<))  $  xxx>>xx=xxx|xx==xx=xx

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

Гольф в буквальном смысле слова сотен байтов благодаря WW и Орджану Йохансену !

объяснение

Функция (??)принимает символ cи строку sи возвращает самый длинный префикс s, который не содержит c. Неуправляемый и не оптимизированный для оценки:

c ?? (y:s)  
    | c==y = ""
    | True = y : c ?? s
c ?? s = s

Функция ssиспользует, (??)чтобы найти самый длинный префикс уникальных символов данной строки:

ss (x:r) = x : (x ?? ss r)
ss "" = ""

(##)это функция, которая принимает две строки и возвращает более длинную. Сравнение длины работает, повторяя строку xтак часто, как xlong ( x>>y) и ylong ( y>>x), и проверяя, какая из полученных строк лексикографически больше.

x ## y
  | (x>>x) < (y>>x) = y
  | True = x

Наконец, ffрекурсивно обрабатывает входную строку, генерирует самый длинный префикс с ss, рекурсивно определяет самую длинную неповторяющуюся подстроку хвоста строки и возвращает длинную из двух с (##):

ff "" = ""
ff (x:r) = ss(x:r) ## ff r

4
224 , в основном путем слияния промежуточного списка.
Орджан Йохансен

2
Я объединил этот ответ с ответом, который я разместил в чате ранее, чтобы получить 216 .
Волшебник Пшеницы

3
209 путем изменения порядка вещей.
Орджан Йохансен

3
С объявлением о вознаграждении я еще раз посмотрел и понял, что @трюк на самом деле стоит 2 байта, а не просто делает ?два символа: 207
Орджан Йохансен

5

Lua, оценка 3, 274 байта

g='g'..'s'..'u'..'b'  _G  [  'l'..'o'..'a'..'d'  ](  g[g  ](  "s  =...f  o  r d = # s - 1 , 0 , - 1 d  o f  or r = 1 , # s - d d  o t = s :s  ub  (r  ,r  +d  )i  f n  ot t:  fi  nd  '(  .)  .*  %1  't  he  n p  ri  nt  (t  )r  et  ur  n en  d e  n  d e  nd  ","  ",""))(...)

Примечание: требуется Lua 5.2 или Lua 5.3

Использование:

$ lua lnrs.lua "Good morning, Green orb!"
ing, Gre
$ lua lnrs.lua "fffffffffff"
f
$ lua lnrs.lua "oiiiiioiiii"
oi
$ lua lnrs.lua "1234567890"
1234567890
$ lua lnrs.lua "11122324455"
324

Основная идея: чередовать все с пробелами, вставлять " "(два пробела), чтобы разделить длинные идентификаторы

Ungolfed код:

g = "gsub"
_G["load"](
   g[g](      -- g[g] == string.gsub - a function for substitution of substrings
      "The source of actual program, but two-space sequences were inserted in some places", 
      "  ",   -- we are replacing all two-space substrings
      ""      -- with an empty string
   )
)(...)

Актуальная программа (после удаления всех пар пробелов):

s = ...
for d = #s - 1, 0, -1 do
   for r = 1, #s - d do
      t = s:sub(r, r+d)
      if not t:find"(.).*%1" then
         print(t)
         return
      end
   end
end

Кстати, фрагмент кода JS для подсчета очков не работает в моем коде.


4

Сетчатка 0.8.2 , 37 байт, оценка 9

.
$&$'¶
(.)(?<=\1.+).*

O#$^`
$.&
1G`

Попробуйте онлайн! Прямой перевод этого ответа на Retina 1 экономит байт, используя Nвместо O#. Однако, если вы наивно играете в ответ Retina 1 до 28 байт, его результат возрастает до 10! Объяснение:

.
$&$'¶

Генерация всех суффиксов ввода.

(.)(?<=\1.+).*

Для каждого суффикса используйте префикс до первого дублированного символа.

O#$^`
$.&

Сортируйте оставшиеся строки в обратном порядке по длине (т.е. сначала по длине).

1G`

Возьми самый длинный.


4

Желе , оценка 2, 14 байт

Ẇµµff  Q  €  Ṫ

Спасибо @JonathanAllan за оценку -1, +7 байт и за замечание ошибки.

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

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

Ẇµµff  Q  €  Ṫ  Main link. Argument: s (string)

Ẇ               Window; yield all substrings of s, sorted by length.
 µ              Begin a new chain. Argument: A (array of substrings)
  µ             Begin a new chain. Argument: A (array of substrings)
   f            Filter A by presence in itself. Does nothing.
       Q  €     Unique each; deduplicate all strings in A.
    f           Filter A by presence in the array of deduplicated substrings,
                keeping only substrings composed of unique characters.
             Ṫ  Tail; take the last (longest) kept substring.

4

Чисто , оценка 7 5, 276 байт

@[ss:s]=rr(pp[][ss:s])((@s))
@s=s
ee x[rr:xx]|e x rr=True=ee x xx
ee x xx=f
f=e'e'' '
e::!  Char  !  Char  ->Bool
e  _ _=  code  {

eqC
}
pp p[r:rr]|ee r p=p=pp(a r p)rr
pp a _=a
a  x[ll:l]=[ll:a x  l]
a l ll=[l]
l[]rr=e'l''l'
l ff[]=f

l[r:rr][ss:ll]=l rr ll
rr x y|l x y=y=x

Попробуйте онлайн! Спасибо @ Οurous за то, что показали мне, что можно вызывать машинный код ABC прямо из Clean. Это позволяет избавиться от предыдущего узкого места, в importкотором минимальный балл был равен 7, но codeдля этого подхода необходимо ключевое слово, которое устанавливает минимальный балл 5.

Разгруженную и не оптимизированную по счету версию вышеуказанного кода можно найти здесь: попробуйте онлайн!


Предыдущая версия со счетом 7, 158 154 130 байтов

import  StdEnv  
@[xx:rr]=c(%[][xx:rr])(@rr)
@e=e
c s b|  length  s<  length  b=b=s
%s[xx:r]|  isMember xx s=s= %(s++[xx])r
%r _=r

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

При этом importоценка не может быть ниже 7. Без импорта нужно было бы реализовать равенство в строках или символах без каких-либо библиотечных функций, что, вероятно, невозможно, как видно из новой версии выше.


1
Вы действительно можете реализовать равенство, используя встроенную ABC, что должно уменьшить счет. Я вернусь с предложенной модификацией позже сегодня, если вам интересно.
Οurous

Например: char равенство: tio.run/##S85JTcz7/…
Οurous

@Ourous A code block with raw ABC instructions, which can be used for primitive functions like integer addition, for linking with C, bypassing the type system... welcome down the rabbit hole!( от cloogle ) звучит привлекательно. Я посмотрю завтра, спасибо за предложение!
Лайкони

1
@ Οurous Еще раз спасибо, благодаря тесту на равенство символов теперь 5
баллов.

Кстати, вам не нужен ни один -ILфлаг, поскольку ничего не импортируется.
Οurous

3

Python 3 , оценка 4, 155 байт

exec(('l=la''mbd''a f'',e=en''ume''rat''e:m''ax''([f[ j  :k]  for  j,i in e ( f)f''or  k,i in e ( f )if  len  ( { *''f[j'':k]''})==k-''j],''key''=le''n)'))

Это определяет функцию l.

Спасибо @xnor за указание на то, что строки длиной 3 не увеличивают счет, сохраняя 32 байта.

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


Строка может быть порциями по 3, верно?
xnor

@xnor Изменение названия функции. Благодарность!
Деннис

3

Брахилог , оценка 2, 19 байт

s  ᶠ  l  ᵒ  ≠  ˢ  t

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

Просто скучный старый ответ "из космоса все вышло". По крайней мере, я узнал, что метапредикаты могут быть удалены от предикатов и все еще работают (а (параметрические) индексы и индексы не могут).

s ᶠ - найти все подстроки данной строки

l ᵒ - упорядочить их по длине (по возрастанию по умолчанию)

≠ ˢ - выберите те, которые имеют все отдельные элементы

t - получить хвост (последний элемент) этого - тот, который имеет наибольшую длину


2

Pyth , 11 байт, оценка 4

-4 оценка благодаря Денису

e lD {I# .:

elD{I#.:Q      Full program, inputs "string" from stdin and outputs to stdout
e              The last element of the list generated by taking
      .:Q      All substrings of the input
     #         Filtered for
   {I          Being invariant over deduplicate i.e. being "non-repeating"
 lD            and sorted by length

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


2

Шелуха , оценка 2, 10 байт

►IIËII≠IIQ

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

объяснение

Программа эквивалентна этому:

►Ë≠Q  Implicit input.
   Q  List of substrings.
►     Find one that maximizes:
 Ë    all ordered pairs
  ≠   are inequal.

Встроенное Ëвычисляет все упорядоченные пары своего аргумента xи возвращает, length(x)+1если каждый результат верен, в противном случае 0. Когда мы максимизируем это, мы находим самую длинную строку без повторяющихся символов.

В представлении я просто вставляю функцию идентификации Iмежду каждой функцией, дважды. Так как это то же самое Ë, I≠то же самое, что и так далее, это не меняет семантику. Единственная опасность состоит в том, что функция более высокого порядка может решить использовать один изI s в качестве аргумента, но, к счастью, это приводит к ошибке типа в нашей программе, поэтому этого не происходит.


2

Clojure, оценка 4

#(  let  [N  (fn  [[_ & r]] r) R  (fn  R [f v c]  (if  c (R f (f v (  nth  c 0))  ( N  c)) v)) C  (fn  C  (  [i]  (C (  seq  i) 0)) ( [i  n]  (if i (C ( N  i )  (  inc n)) n)))  J  (fn  [c  i]  (assoc c (C  c) i)) I  (fn  F [f i n R]  (if ( =  (C  R) n) R (F f (f  i) n ( J  R (f  i)))))] ( apply  str  (R ( fn  [a  b] ( if  (< (C  a)  (C  b)) b a )) "" (  for  [k  (I N % (C  % ) [])]  (R  ( fn [ t  c ] ( if ( or ( = t (  str t) ) ((  set t)c))(apply  str t) ( J  t c)))[]k)))))

О боже, это было больно! Nреализует next, Rесть reduce, Cесть count, Jесть conj(работает только для векторов) и Iесть iterate. apply strесть дважды, потому что в противном случае ввод "aaaa" не вернул бы строку, а вектор [\a]. К счастью, мне пришлось использовать, applyи assocя не знал, что вы можете связать один индекс с последним элементом вектора: o


Я сбрил немного места: попробуйте онлайн!
Орджан Йохансен,

1

Желе , оценка 5, 10 байт

ẆµQQ⁼µÐfµṪ

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


2
Вы можете уменьшить счет до 3, добавив пробелы в коде. Например: ẆµQQ ⁼ µ Ðf µ Ṫ(возможно, теперь добавлено слишком много пробелов, но это всего лишь пример. Я оставлю вам оптимизацию подсчета байтов по сравнению с пробелами).
Кевин Круйссен

1

Python 3 , оценка 4, 317 байт

exec(('%s'  *58  %(  's=','in','pu','t(',');','pr','in','t(','so','rt','ed','((s','[i',':j',']f','or',' j',' i','n ','ra','ng','e(','1,','le','n(','s)','+1',')f','or',' i',' i','n ','ra','ng','e(','j)','if',' l','en','(s','et','(s','[i',':j',']))','==l','en','(s','[i',':j',']))',',k','ey','=l','en',')[','-1','])')))

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

Необработанный код:

s=input();print(sorted((s[i:j]for j in range(1,len(s)+1)for i in range(j)if len(set(s[i:j]))==len(s[i:j])),key=len)[-1])

lambda aсодержит mbda элемент с 5 баллами, и функция нуждается в том, returnчто, очевидно, не может быть execотредактировано (поэтому для него требуется оценка не менее 5 eturn), поэтому была необходима полная программа. Вероятно, можно немного уменьшить размер неиспользованного кода, но я не вижу быстрого и ясного улучшения.


1

Алиса , 40 байт

/ii..nn$$@@BBww..DD~~FF..!!nn$$KK??oo@@

(Завершающий перевод строки)

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

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

i.n$@Bw.D~F.!n$K?o@

i     take input
.n$@  terminate if empty
B     push all nonempty substrings, with the longest on the top of the stack
w     push return address (start main loop)
.     make copy of current substring
D     deduplicate characters
~     swap: this places the original above the deduplicated copy
F     Push the original string if it is a substring of the deduplicated copy
      (which can only happen if they're equal); otherwise push empty string
.!    place a copy on the tape
n$K   if the empty string was pushed, return to start of loop
o     output
@     terminate

1

Perl 6 , оценка: 15 10 8, длина: 46 55 62 байта

{~m:ov/(.+)<!{$0.comb.repeated}>/.max(&chars)}

Попробуй это

{~m:ov/(..*)<!{(($0)).comb.repeated}>{{}}/.max(&chars)}

Попробуй это

{m:ov:i/(..*)<!{(($0)).comb.repeated}>{{}}/.max((&chars)).Str}

Попробуй это

Expanded:

{    # bare block lambda with implicit parameter 「$_」

    m                          # match (implicitly against 「$_」)
    :overlap                   # in every single way possible
    :ignorecase                # add a 「:」 to break up substring
    /

      (..*)                    # match at least one character

      <!{
        (($0)).comb.repeated  # backtrack if there were repeats
      }>

      {{}}                    # anon hash in code block (no-op)
    /

    .max((&chars))            # get the longest

    .Str                      # coerce to a Str (from a Match object)
}

Оценка 5 за 88 байт. Там может быть несколько мест для байтов гольфа, хотя
Джо Кинг

1

Java 8, оценка 9 (384 B) 7 (401 B)

S -> { int s = 0 , e = 0 , l = 0 , x = 0 , y = 0 , b [ ] = new int [ 256 ] ; for ( ; x <S.  length  & y <S.  length  & l <S.  length  - x ; x ++ ) { b [S[x]] = 1 ; for ( y ++ ; y <S.  length  && b [S[y]] < 1 ; b [S[y ++]] = 1 ) ; if ( l < y - x ) { s = x ; e = y ; l = y - x ; } for ( ; y <S.  length  && x < y & S[x] != S[y  ];)b [S[x ++]] = 0 ; }  String g=""; for( ; s<e ; g+= S[s++]);  return  g;}
  • Первоначальный вариант. Спустимся отсюда. Оценка 9 из-за "ubstring ", поэтому substringбудет первая часть, чтобы заменить.
  • Счет сейчас 7, из-за " length"которого я, вероятно, не смогу снизить дальше .. Я сомневаюсь, что можно отказаться от четырех вариантов использования length. Если это возможно, " eturn"(6) может понизить счет на 1 как окончательное улучшение, но я думаю, что это так (за исключением, может быть, небольшого уменьшения количества байтов ..)

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



0

Mathematica, score 11 9

Length@Last@Select[Subsequences[Characters@#],#==DeleteDuplicates  @#&]&

Shaving a couple of bytes off of the longest nonrepeating string by obscuring the function's name:

Length@Last@Select[Subsequences[Characters  @#],#==(  ToExpression@ 
StringJoin@@FromCharacterCode@{{68},{101},{108},{101},{116},{101},{68},{117},
{112},{108},{105},{99},{97},{116},{101},{115}}))@#&]&

0

Kotlin, score: 11 10 9 bytes, length: 227 246 245 bytes

indices
  .flatMap { p -> indices . map { p to p + it } }
  .  filter { (r,i) -> i < length  }
  .map { ( s , a )->substring  (  s,  a  ) }
  .  filter { it  .  groupBy  { it } .  none { ( k , v )->v . size>1 } }
  .maxBy { it.length }

The longest is ubstring, which is 9 chars

It is called like this:

val c = "Good morning, Green orb!"

fun String.c(): String? = indices
    .flatMap { p -> indices . map { p to p + it } }
    .  filter { (r,i) -> i < length  }
    .map { ( s , a )->substring  (  s,  a  ) }
    .  filter { it  .  groupBy  { it } .  none { ( k , v )->v . size>1 } }
    .maxBy { it.length }

fun main(args: Array<String>) {
    val text = """indices
    .flatMap { p -> indices . map { p to p + it } }
    .  filter { (r,i) -> i < length  }
    .map { ( s , a )->substring  (  s,  a  ) }
    .  filter { it  .  groupBy  { it } .  none { ( k , v )->v . size>1 } }
    .maxBy { it.length }"""
    val message = text.c()!!
    println(message)
    println(text.length)
    println(message.length)
    println(c.c())
}

Aren't you able to reduce it to 10 by adding an additional space between roupingBy and {?
Kevin Cruijssen

1
Nice find, I changed the other 11s and and got down to 10
jrtapsell

It is 10 chars, but the longest substring isn't roupingBy (which is 9 chars) but eachCount (with trailing space).
Erik the Outgolfer

roupingBy has a trailing space (visible in the markdown, but the renderer seems to strip it)
jrtapsell

Managed to reduce it to 9, fixing the trimming issue
jrtapsell


0

05AB1E, 22 bytes | Score: 2

Œ  ʒ  D  Ù  Q  }  é  ¤

-1 score + 7 bytes thanks to HeebyJeeby

Try it online!


05AB1E, 15 bytes | Score: 3

Œ ʒ D Ù Q } é ¤

Try it online!


05AB1E, 8 bytes | Score: 8

ŒʒDÙQ}é¤

Try it online!


05AB1E can actually do something rather cheap... adding whitespace into 05AB1E does nothing.

If there is a rule against this, I can also use ´ and like 7 other chars.


1
@HeebyJeebyMan because I'm a moron, got a problem with that?
Magic Octopus Urn

@HeebyJeebyMan kidding haha, thanks for the idea.
Magic Octopus Urn
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.