728x90
2866번: 문자열 잘라내기
첫 번째 줄에는 테이블의 행의 개수와 열의 개수인 R과 C가 주어진다. (2 ≤ R, C ≤ 1000) 이후 R줄에 걸쳐서 C개의 알파벳 소문자가 주어진다. 가장 처음에 주어지는 테이블에는 열을 읽어서 문자
www.acmicpc.net
📄 문제개요
- R개의 행과 C개의 열로 주어진 테이블이 입력으로 주어진다. 이 테이블의 원소는 알파벳 소문자이다.
- 각테이블의 열을 위에서 아래로 읽어서 하나의 문자열로 만들 수 있다.
- 2 ≤ R, C ≤ 1000
🤔 문제분석
- 문자는 최대 1000개와 문자의 길이는 1000을 갖을 수 있다.
- 완전탐색의 경우 최악의 경우 O($N^3$)이다.
- 최악의 경우 1000번 반복하는데, 모든 문자의 중복을 확인( 1000 * 1000 ) 해야한다.
- O($N^2log(N)$)의 시간복잡도로 풀 수 있도록 생각을 해봐야 한다.
- words 라는 문자를 담은 배열이 있을때, words를 순회하는 word가 words안에 2개 이상 있는것을 찾아낸다면 중복이 있는것이다.
- words 라는 배열 크기는 N 이다.
- words를 순회하면서 word안에 있는 개수를 파악한다. ( 이분탐색 )
- 총 길이가 1000임으로 O($N^2log(N)$)의 시간복잡도로 풀 수 있다.
📝 의사코드
- words를 입력받는다.
- words를 정렬한다.
- 문자열의 길이를 줄여보면서 중복값이 있는지 확인한다.
- 하나의 word가 words안에 중복값이 있는경우를 확인한다.
- 중복값이 있다면 종료하고, 중복값이 없다면 +1 을 한뒤 3번으로 다시 간다.
💻 코드
import sys
input = sys.stdin.readline
R, C = map(int, input().split()) # 행, 열
words =['' for _ in range(C)]
for _ in range(R):
temp = input().strip()
for j in range(C):
words[j] += temp[j]
words.sort()
def search_cnt(array, query):
start = 0
end = len(array) - 1
left_idx = None
while start <= end:
mid = (start + end) // 2
temp = array[mid]
if temp >= query:
left_idx = mid
end = mid - 1
else:
start = mid + 1
start = 0
end = len(array) - 1
right_idx = None
while start <= end:
mid = (start + end) // 2
temp = array[mid]
if temp <= query:
right_idx = mid
start = mid + 1
else:
end = mid - 1
#print(right_idx, left_idx, query, array)
return right_idx - left_idx + 1
start = 1
ans = 0
while start < R:
flag = False
words = [word[1:] for word in words]
words.sort()
for word in words:
s_cnt = search_cnt(words, word)
#print(s_cnt, word, start)
if s_cnt > 1: # 중복이 있다면
flag = True
break
if flag:
break
else:
ans += 1
start += 1
print(ans)
🎯 피드백 및 개선사항
- 해당문제는 문자를 정렬을 하지 않아서 어디서 문제가 발생하였는지 헛 시간을 투자했습니다.
- word를 한번 슬라이싱 한뒤, 정렬을 해야하는데 정렬을 하지 않아서 한참 해맸습니다.
words = [word[1:] for word in words]
words.sort()
❓다른사람은 어떻게 풀었을까?
- 문자열의 길이가 R일때, start = 0, end = R-1 로 두고 mid 값 이후의 문자열값을 비교한다.
- 만약 mid값 이후의 문자열중에서 중복값이 존재한다면 mid값의 크기를 낮춰야 한다.
- 만약 mid값 이후 문자열 중에서 중복값이 존재하지 않는다면 mid값의 크기를 키운다.
- 집합 자료구조를 활용하여 중복체크를 확인합니다. C와 집합 자료구조의 길이를 확인한다.
n, m = map(int,input().split(' '))
words = [''] * m
left,right = 0,n-1
for _ in range(n):
for i, char in enumerate(input()):
words[i] += char
def dup(mid):
nodup = set()
for word in words:
nodup.add(word[mid:])
return len(nodup) != m
answer = 0
while left <= right:
mid = (left+right) // 2
if dup(mid):
right = mid-1
else:
answer = mid
left = mid+1
print(answer)
728x90
'알고리즘 > 백준' 카테고리의 다른 글
[백준] 1106번 : 호텔 (1) | 2023.11.19 |
---|---|
[백준] 2629번 : 양팔저울 (0) | 2023.11.19 |
[백준] 1920번 : 수 찾기 (1) | 2023.11.18 |
[백준] 10825번 : 국영수 (0) | 2023.11.18 |
[백준] 7453번 : 합이 0인 네 정수 (1) | 2023.11.18 |