문자열의 런 계산


11

W. Rytter 에 의한 문자열의 런 수 에서 가져온 다음 정의를 고려하십시오 . 단어, 문자열 및 하위 문자열은 모두 대략 동의어입니다.

문자열에서 실행은 문자열에서 확장 불가능한 (최소 동일한 기간으로)주기 세그먼트입니다.

단어 w의주기 p는이 방정식의 양변이 정의 될 때마다 w [i] = w [i + p]가되도록 임의의 양의 정수 p이다. per (w)가 w의 가장 작은주기의 크기를 나타냅니다. 단어 w는 per (w) <= | w | / 2이다.

예를 들어 string을 고려하십시오 x = abcab. per(abcab) = 3x[1] = x[1+3] = a, x[2]=x[2+3] = b더 작은 기간이 없습니다. 따라서 문자열 abcab은 주기적이 아닙니다. 그러나 문자열 abab은 per (abab) = 2로 주기적입니다.

문자열 w에서 런 (또는 최대 주기성)은 j> = i 인 간격 [i ... j]입니다.

  • w [i ... j]는 p = per (w [i ... j])의주기 단어입니다.
  • 최대입니다. 공식적으로 w [i-1] = w [i-1 + p]도 w [j + 1] = w [j + 1-p]도 아닙니다. 비공식적으로, 실행은 같은 기간의 더 큰 실행에 포함될 수 없습니다.

RUNS (w)는 w의 런 집합을 나타냅니다.

4 개의 실행 atattatt은 [4,5] = tt, [7,8] = tt, [1,4] = atat, [2,8] = tattatt입니다.

문자열 aabaabaaaacaacac에는 다음과 같은 7 개의 실행이 포함됩니다.

[1,2] = aa, [4,5] = aa, [7,10] = aaaa, [12,13] = aa, [13,16] = acac, [1,8] = aabaabaa, [9 , 15] = aacaaca.

결과는 런 목록이어야합니다. 각 실행은 그것이 나타내는 간격을 지정해야하지만 부분 문자열 자체를 출력 할 필요는 없습니다. 정확한 형식은 편리한 것이 될 수 있습니다.

예제는 1- 인덱싱을 사용하지만보다 편리한 경우 0- 인덱싱을 자유롭게 사용할 수 있습니다.

직무

문자열 w, 출력 RUNS (w)를 제공 한 코드를 작성하십시오.

언어와 입력

원하는 언어를 사용하고 가장 편리한 형식으로 입력 문자열을 사용할 수 있습니다. 그러나 전체 프로그램을 제공해야하며 예제 입력에서 실행되는 코드 예제를 보여 주어야합니다.


4
좋은 도전이지만 기본 을 무시 하고 기능을 허용하지 않는 좋은 이유가 있습니까?
마틴 엔더

@MartinEnder 그것은 단지 내 취향입니다. 사람들이 코드를 복사하여 붙여넣고 직접 사용해 보는 것이 더 쉬워 지므로 더 많은 사람들이 답을 더 흥미롭게 만들 수 있습니다.

4
그러나 그로 인해 많은 오버 헤드 코드가 발생하여 자세한 구문으로 언어에 대한 경쟁이 불공평합니다. 예를 들어 class A{public static ...}골프 코드 를 작성 하고 싶을 때마다 작성해야한다면 Java에서 골프를 치지 않을 것입니다.
Bassdrop Cumberwubwubwub

@BassdropCumberwubwubwub 장단점이 있다는 것을 알 수 있습니다. 나는 프로를 더 강력하게 평가합니다. 예를 들어 APL을 파이썬과 비교하는 것보다는 비슷한 언어로 골프 답변의 길이를 비교하는 것이 가장 흥미 롭습니다.

"런은 더 큰 런 내에 완전히 포함되지 않으면 최대"이지만 첫 번째 예에서 [7,8]은 [2,8]에 완전히 포함됩니다. 아니면 동일한 하위 문자열을 반복하는 실행에 대해 엄격하게 이야기하고 있습니까?
SE가 EVIL이기 때문에 aditsu가 종료 됨

답변:


2

Pyth, 38 바이트

{smm,hk+ekdfgaFTdcx1xM.ttB+0qVQ>QdZ2Sl

  m                                 SlQ   map for d in [1, …, len(input)]:
                            qVQ>Qd          pairwise equality of input[:-d] and input[d:]
                        tB+0                duplicate this list, prepending 0 to one copy
                      .t          Z         transpose, padding with 0
                    xM                      pairwise xor
                  x1                        find all occurrences of 1
                 c                 2        chop into groups of 2
           f                                filter for groups T such that:
             aFT                              the absolute difference between its elements
            g   d                             is greater than or equal to d
   m                                        map for groups k:
     hk                                       first element
    ,  +ekd                                   pair with the last element plus d
 s                                        concatenate
}                                         deduplicate

테스트 스위트


"atattatt"에서 "[[3, 5], [6, 8], [0, 4], [1, 8]]"을 얻습니다. [3,5]는 "tt"를 나타 냅니까? 사용한 알고리즘을 높은 수준으로 설명 할 수 있다면 좋을 것입니다.

@Lembik 예 [i, j](0 인덱스) 문자 사이 슬라이스 시작 나타내고 i-1i문자 사이의 종료 j-1j. 이것은 Pyth와 대부분의 제정신 언어의 표준 규칙입니다 ( 여기여기 참조 ).
Anders Kaseorg

큰. 솔루션을 직관적으로 설명 할 수 있습니까? 불행히도 코드 설명에서 리버스 엔지니어링 할 수 없습니다.

1
@Lembik d의 런을 찾고 있다고 가정하자. d. 문자 i가 문자 i + d와 일치하는 모든 위치를 찾습니다. 그런 다음 그러한 위치에서 적어도 연속 된 런을 찾습니다. 모든 d에 대해 반복하십시오. 실제 기간은 d의 제수 일 뿐이므로 마지막에 중복 제거해야합니다.
Anders Kaseorg

1

CJam, 66

q:A,2m*{~A>_@)_@<2*@@2*<=},{_2$-2>2,.+={+}&}*]{[_1=\)\0=2*)+]}%_&p

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

간단한 설명 :

이 알고리즘은 4 단계로 작동합니다 (처음 3 개는 관찰 할 수있는 3 개의 주요 블록에 해당).

  1. 쌍을 모두 [길이 인덱스]를 찾아 낸다 (예로서 중복 된 문자열에 대응 ABA의 ABA의 aaacaacac); 이것들은 달리기의 일부입니다.
  2. 동일한 런에 속하는 쌍, 즉 연속 인덱스 및 동일한 길이 / 기간을 연결합니다.
  3. 최소 지수와 최대 지수 + 2 * 길이-1을 취하여 실제 런을 구성합니다.
  4. 마지막에 중복 된 런을 제거합니다 (다른 주기로 얻은 동일한 간격).

골프를 더하고 싶기 때문에 이것은 모두 변경 될 수 있습니다.


감사합니다. 사용한 알고리즘도 설명해 주시겠습니까?

1
@Lembik ok, 업데이트
SE가 EVIL이기 때문에 aditsu가 종료
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.