사용자 도구

사이트 도구


ps:problems:boj:28064

이민희진

ps
링크acmicpc.net/…
출처BOJ
문제 번호28064
문제명이민희진
레벨실버 5
분류

문자열

시간복잡도O(n^2*m)
인풋사이즈n<=100, m<=20
사용한 언어Python 3.11
제출기록31388KB / 88ms
최고기록76ms
해결날짜2023/05/27

풀이

  • O(n^2)개의 모든 이름 쌍에 대해서 연결 가능한지 여부를 확인하면 된다.
  • 두개의 이름 n1, n2가 연결 가능한지를 확인하는 가장 나이브한 방법은, n1[:i] 와 n2[-i:]이 같은지를 1≤i≤min(|n1|,|n2|)+1 인 모든 i에 대해서 확인해보는 것이다. l= min(|n1|,|n2|) 이라 하면, O(l^2)의 시간이 걸린다.
  • 조금 더 효율적인 방법은. n1과 n2를 이어붙인 문자열 S를 만들고, S의 border 중에서 길이가 l 이하인 것이 있는지 확인해보는 것이다. KMP알고리즘이나 Z알고리즘을 사용하면 O(|S|)에 처리할수 있다.
  • 문자열의 최대 길이를 m이라고 하면, 연결 가능성을 확인하는 나이브한 방식은 O(m^2), 효율적인 방식은 O(m)이고, 전체 시간복잡도는 O(n^2*m^2) 또는 O(n^2*m)이 된다. 여기에서는 m의 범위가 최대20 으로 매우 작기 때문에, 나이브한 방식이 실제로는 더 빠르게 돌아간다.

코드

코드 1 - 나이브

"""Solution code for "BOJ 28064. 이민희진".

- Problem link: https://www.acmicpc.net/problem/28064
- Solution link: http://www.teferi.net/ps/problems/boj/28064
"""

import itertools


def main():
    N = int(input())
    names = [input() for _ in range(N)]

    answer = 0
    for n1, n2 in itertools.combinations(names, 2):
        if (any(n2.endswith(n1[:i]) for i in range(1, len(n1) + 1))) or (
            any(n1.endswith(n2[:i]) for i in range(1, len(n2) + 1))
        ):
            answer += 1

    print(answer)


if __name__ == '__main__':
    main()

코드 2 - 효율적

"""Solution code for "BOJ 28064. 이민희진".

- Problem link: https://www.acmicpc.net/problem/28064
- Solution link: http://www.teferi.net/ps/problems/boj/28064
"""

import itertools
from teflib import string as tstring


def main():
    N = int(input())
    names = [input() for _ in range(N)]

    answer = 0
    for n1, n2 in itertools.combinations(names, 2):
        l = min(len(n1), len(n2))
        for s in [n1 + n2, n2 + n1]:
            z = tstring.z_array(s)
            if any(i == z_i <= l for i, z_i in enumerate(reversed(z), start=1)):
                answer += 1
                break

    print(answer)


if __name__ == '__main__':
    main()

토론

댓글을 입력하세요:
H F J E B
 
ps/problems/boj/28064.txt · 마지막으로 수정됨: 2023/05/27 15:20 저자 teferi