최단 고유 하위 문자열


14

STDIN에서 명령 행 인수 또는 함수 인수로 두 개의 고유하고 비어 있지 않은 문자열이 주어지면 두 번째의 하위 문자열이 아닌 첫 번째 문자열의 가장 짧은 하위 문자열을 찾아 리턴하십시오. 이러한 하위 문자열이 없으면 빈 문자열을 반환하거나 원래 문자열의 하위 문자열이 아닌 문자열을 반환하거나 예외를 throw 할 수 있습니다. 함수에서 돌아 오는 경우이 경우 null (또는 undefined, None 등)을 반환 할 수도 있습니다. 이러한 하위 문자열이 여러 개 최단으로 묶인 경우 그 중 하나를 반환 할 수 있습니다.

문자열은 인쇄 가능한 ASCII 문자로 구성 될 수 있습니다.

STDIN에 제공된 입력은 각 행에 하나의 문자열로 제공됩니다. 귀하의 요청에 따라 입력 끝에 빈 줄이 하나 추가 될 수 있습니다.

이것은 코드 골프이므로 가장 짧은 유효한 프로그램이 승리합니다.

일부 테스트 사례

입력:

STRING ONE
STRING TWO

산출:

E

입력:

A&&C
A&$C

유효한 출력 :

&&
&C

입력:

(임의로 생성 된 80 자 문자열 2 개)

QIJYXPYWIWESWBRFWUHEERVQFJROYIXNKPKVDDFFZBUNBRZVUEYKLURBJCZJYMINCZNQEYKRADRYSWMH
HAXUDFLYFSLABUCXUWNHPSGQUXMQUIQYRWVIXGNKJGYUTWMLLPRIZDRLFXWKXOBOOEFESKNCUIFHNLFE

모든 유효한 출력 :

AD
BJ
BR
CZ
DD
EE
ER
EY
EY
FF
FJ
FW
FZ
HE
IJ
IN
IW
JC
JR
JY
KL
KP
KR
KV
LU
MH
MI
NB
NQ
OY
PK
PY
QE
QF
QI
RA
RB
RF
RO
RV
RY
RZ
SW
UE
UH
UN
UR
VD
VQ
VU
WB
WE
WI
WU
XN
XP
YI
YK
YK
YM
YS
YW
YX
ZB
ZJ
ZN
ZV

1
최단 또는 최장?
Leaky Nun

@FryAmTheEggman 그래도 여전히 솔루션을 게시해야합니까?
Leaky Nun

따옴표가 있거나없는 "각 줄에 하나의 문자열"?
Leaky Nun

1
우리는 문자열 배열을 취할 수 있습니까?
Dennis

"B"는 "aBc"의 하위 문자열입니까?
downrep_nation

답변:


4

Brachylog , 23 바이트

:1foh.,{,.[A:B]hs?'~sB}

이전 Java 트랜스 필러에서 작동합니다. 목록의 두 문자열을 입력으로 예상하고 하위 문자열과 출력을 통합합니다. 하위 문자열이 없으면 false를 반환합니다.

불행히도 아직 새로운 프롤로그 변환기에 내장 된 서브 세트를 코딩하지 않았습니다.

설명

:1f               Find all bindings which satisfy predicate 1 with that binding as input and
                  with the Input of the main predicate as output.
   oh.,           Order that list of bindings, and unify the output with the first one.

{
 ,.[A:B]          Unify the output with the list [A,B]
        hs?       Unify the input with a subset of A
           '~sB   Check that no subset of B can be unified with the input
               }

4

파이썬 (119) 115 91

lambda a,b:[a[m:m+n]for n in range(1,len(a)+1)for m in range(len(a))if a[m:m+n]not in b][0]

테스트 사례 :

| Input 1  | Input 2     | Output        |
|----------+-------------+---------------|
| 'abcd'   | 'abc'       |  'd'          |
| 'abcd'   | 'dabc'      |  'cd'         |
| 'abcd'   | 'dcbabbccd' |  'abc'        |
| 'abcdf'  | 'abcdebcdf' |  'abcdf'      |
| 'abc'    | 'abc'       |  (IndexError) |

더 짧게 만들기 위해 노력하고 있지만 이것은 나의 두뇌 본능입니다. 아직은 골퍼가 아닙니다.

여분의 바이트에 대해 @ user81655와 @NonlinearFruit에게 감사합니다.

편집 :

댕 이 코드를 시도했다 :

def z(a,b):
 for s in [a[m:m+n]for n in range(1,len(a)+1)for m in range(len(a)-n+1)]:
  if s not in b:return s
 return''

몇 바이트 짧아 졌다고 생각했습니다. 편집하기 전에했던 것보다 1 바이트 길었습니다.


나는 많은 파이썬을 모른다.하지만 어쩌면 당신은 (r=range)(1,len(a)+1)사용할 수 r있습니까?
Conor O'Brien

@ CᴏɴᴏʀO'Bʀɪᴇɴ 그렇게 할 수 없습니다. 내가 지정하는 경우 ranger위의 라인, 실제로 바이트를 추가합니다. 그래도 좋은 생각입니다. 부분 문자열을 반복하는 더 짧은 방법이있을 것입니다.
Taylor Lopez

range(1,len(a))그리고 range(len(a)-1)그것은 안 일을해야합니까? 또한 두 공백 들여 쓰기에 탭 문자를 사용하면 바이트를 절약 할 수 있다고 생각합니다.
user81655

아니요,를 사용 range(1,len(a))하면 4 번째 테스트 캐스트가 전체 문자열을 시도하지 않기 때문에 실패합니다. 문자열-1의 길이로만 이동합니다. 그리고를 사용 range(len(a)-1)하면 첫 번째 테스트 사례가 'cd'just 대신 반환 되지 않습니다 'd'. 그래도 뭔가있을 수 있습니다.
Taylor Lopez

죄송합니다. Python에 익숙하지 않으며 범위가 포함 된 것으로 가정했습니다. 이 경우 시도 range(1,len(a)+1)하고 range(len(a)).
user81655

3

파이썬, 87 86 바이트

lambda s,t,e=enumerate:[s[i:i-~j]for j,_ in e(s)for i,_ in e(s)if(s[i:i-~j]in t)<1][0]

존재하는 경우 가장 짧은 고유 한 부분 문자열 중 가장 왼쪽을 반환합니다.

고유 한 하위 문자열이 없으면 IndexError 가 발생합니다.

Ideone에서 테스트하십시오 .


거기는. 누군가 내가 람다가 아닌 구현을 죽일 때까지 기다리고있었습니다. nice lol
Taylor Lopez

난 당신이 할 수있는 선택적인 두 번째 인수 제공하여이 짧은을 할 수 있다고 생각 enumerate시작 j에를 i+1.
user2357112는

@ user2357112 불행히도 NameError 가 발생합니다 . 코드는 j먼저 정의한 다음을 정의합니다 i.
Dennis

@Dennis : 네,하지만 꼭 그럴 필요는 없습니다. 루프 순서를 전환 할 수 있습니다.
user2357112는

1
@ user2357112 루프 순서를 전환하면 찾은 첫 번째 고유 하위 문자열이 가장 짧지 않을 수 있습니다. 단순히 주문을 바꾸면 'ab'input이 반환 됩니다 'abc','aaa'.
Dennis

2

파이썬, 82 바이트

g=lambda u:{u}|g(u[1:])|g(u[:-1])if u else{''}
f=lambda s,t:min(g(s)-g(t),key=len)

사용법 : f('A&&C', 'A&$C')-> 반환'&&'

적합한 하위 문자열이 없으면 ValueError가 발생합니다.

설명:

g=lambda u:{u}|g(u[1:])|g(u[:-1])if u else{''}일련의 하위 문자열을 재귀 적으로 생성 u f=lambda s,t:min(g(s)-g(t),key=len)하여 설정된 차이에서 가장 짧은 하위 문자열을 취합니다.


2

자바 스크립트 (ES6), 79 바이트

f=
(a,b)=>[...a].some((_,i,c)=>c.some((_,j)=>b.indexOf(s=a.substr(j,i+1))<0))?s:''
<div oninput=o.textContent=f(a.value,b.value)><input id="a"/><input id="b"/><pre id=o>

돌아 오는 경우 false 할 수있는&&s 대신을 사용하여 2 바이트를 저장하십시오 ?s:''.



1

자바 스크립트 (Firefox), 80 바이트

solution=

a=>b=>[for(_ of(i=0,a))for(_ of(j=!++i,a))if(b.includes(s=a.substr(j++,i)))s][0]

document.write("<pre>"+
[ [ "test", "best" ], [ "wes", "west" ], [ "red", "dress" ] ]
.map(c=>c+": "+solution(c[0])(c[1])).join`\n`)

테스트는 Firefox에서만 작동합니다. undefined부분 문자열이없는 경우 반환 합니다.


문자열에는 \ 또는 다른 RegExp 메타 문자와 같은 인쇄 가능한 ASCII 문자가 포함될 수 있지만 Firefox로 제한하는 경우 b.includes대신 사용 하지 않겠습니까?
Neil

@ Neil이 질문은 문자열이 문자가 될 수 있다고 말하지 않았지만 알려 주셔서 감사합니다! 를 사용하도록 업데이트되었습니다 includes.
user81655

1
시험 조각은 발생SyntaxError: unexpected token 'for'
NoOneIsHere

@NoOneIsHere 파이어 폭스를 사용하지 않을 경우 발생하는 오류입니다.
user81655

1

망막 , 37 바이트

M!&`\G(.+?)(?!.*¶.*\1)
O$#`.+
$.&
G1`

에 유효한 하위 문자열이 없으면 출력이 비어 A있습니다.

온라인으로 사용해보십시오! (한 번에 여러 테스트 사례를 실행하도록 약간 수정되었습니다. 입력 형식은 실제로 줄 바꿈으로 구분되지만 테스트 스위트는 한 줄에 하나의 테스트 사례로 작성하는 것이 가장 쉽습니다. 테스트 프레임 워크는 실제 코드가 시작되기 전에 공백을 줄 바꿈으로 바꿉니다.)

설명

M!&`\G(.+?)(?!.*¶.*\1)

의 가능한 시작 위치마다에 A나타나지 않는 가장 짧은 부분 문자열을 일치시킵니다 B. 는 &우리가 실제로 일치 한 문자보다 긴 경우에도, 모든 시작 위치를 시도하도록 경기를 중복입니다. 이를 \G통해 우리는 어떤 위치도 건너 뛰지 않습니다. 특히이 방법으로 줄 바꿈에서 멈추어야하므로 추가 일치를 얻지 못합니다 B. 이것이 엉망이되지 않는 이유는 실제로 미묘합니다. 왜냐하면 A유효한 하위 문자열을 찾을 수없는 위치에 시작 위치 가 있으면 인해 실패가 발생\G 있으면 더 이상 위치 확인을 중지 . 그러나 (현재 시작 위치에서) 모든 하위 문자열이B, 현재 위치에서 더 오른쪽으로 시작하는 모든 하위 문자열도 마찬가지이므로이를 버리는 것은 문제가되지 않으며 실제로 성능을 향상시킵니다.

M!구성 으로 인해 이러한 모든 일치 항목이 스테이지에서 리턴되어 라인 피드와 결합됩니다.

O$#`.+
$.&

이전 결과의 행을 길이별로 정렬합니다. 행을와 일치시켜 수행합니다 .+. 그런 다음 $"sort-by"형식을 활성화하여 일치하는 항목을$.& 정렬 순서를 결정하기 위해 합니다. $.&자체는 길이와 일치를 대체합니다. 마지막 #으로이 옵션은 Retina에 숫자로 정렬하도록 지시합니다 (그렇지 않으면 결과 숫자를 문자열로 처리하고 사전 식으로 정렬합니다).

G1`

마지막으로 빈 정규식 (항상 일치)과 제한을 가진 grep 스테이지를 사용하여 첫 줄만 유지합니다 1.


1

펄, 87 85

sub{(grep{$_[1]!~/\Q$_/}map{$}=$_;map{substr($_[0],$_,$})}@}}(@}=0..length$_[0]))[0]}

이 함수 $_[0]는에 나타나지 않는 가장 짧은 하위 문자열의 첫 번째 (위치 별)를 반환 $_[1]하거나 undef해당 하위 문자열이없는 경우 익명 함수입니다 .

@iAmMortos의 답변에서 가져온 문자열로 테스트 프로그램을 Perl 5.22.1로 테스트했습니다.

#!/usr/bin/perl -l
use strict;
use warnings;

my $f = <see above>;
print $f->('abcd', 'abc');
print $f->('abcd', 'dabc');
print $f->('abcd', 'dcbabbccd');
print $f->('abcdf', 'abcdebcdf');
print $f->('abc', 'abc');

1

하스켈, 72 바이트

import Data.Lists
a#b=argmin length[x|x<-powerslice a,not$isInfixOf x b]

사용 예 : "abcd" # "dabc"-> "cd".

간단한 구현 :의 모든 하위 문자열을 빌드하고에 a표시되지 않는 문자열을 유지하십시오 b. argmin두 번째 인수가 주어지면 함수를 최소화하는 목록의 요소를 반환합니다 length.


나는 몰랐다 argmin! 매우 유용한 것 같습니다.
Zgarb

0

종료 9는 여전히 9입니다
고양이

이것이 어떻게 작동하는지 알고 싶습니다.
mroman

@mroman the. : 하나의 인수로 모든 하위 요소가 있습니다. 그래서 두 문자열에 걸쳐 매핑 한 다음 setwise diff를 접습니다. 그래서 두 번째 arnt의 첫 번째 substr을 모두 얻은 다음 가장 작은 cuz. :가 정렬됩니다.
말 티센

0

C #, 152 바이트

string f(string a,string b){int x=a.Length;for(int i=1;i<=x;i++)for(int j=0;j<=x-i;j++){var y=a.Substring(j,i);if(!b.Contains(y))return y;}return null;}

0

루비, 70 바이트

첫 번째 문자열에서 특정 길이의 하위 문자열을 모두 수집하고 두 번째 문자열에없는 문자열을 반환합니다.

->a,b{r=p;(1..l=a.size).map{|i|(0...l).map{|j|b[s=a[j,i]]?0:r||=s}};r}

0

해 학적 인 -26 바이트

지금 내가 할 수있는 가장 짧은 방법은 다음과 같습니다.

lnp^sujbcjz[{^p~[n!}f[-][~

0

apt , 14 바이트

Êõ!ãU c k!èV g

온라인으로 사용해보십시오!

유효한 부분 문자열undefined없는 경우 반환 합니다 . 문자열 "undefined"반환하는 것과는 다르지만 -Q 플래그로 인해 차이점 만 볼 수 있습니다.

설명:

Ê                 :Length of the first input
 õ                :For each number in the range [1...length]:
  !ãU             : Get the substrings of the first input with that length
      c           :Flatten to a single array with shorter substrings first
        k         :Remove ones which return non-zero to:
         !èV      : Number of times that substring appears in second input
             g    :Return the shortest remaining substring

0

Japt -h, 11 바이트

à f@øX «VøX

시도 해봐

                :Implicit input of strings U & V
à               :All combinations of U
  f@            :Filter each as X
    øX          :  Does U contain X?
       «        :  Logical AND with the negation of
        VøX     :  Does V contain X?
                :Implicit output of last element
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.