2014 - Longest Subsequence Repeated k Times
정보
- 문제 보기: 2014 - Longest Subsequence Repeated k Times
- 소요 시간: 25분 25초
- 풀이 언어:
java - 체감 난이도: 3️⃣~4️⃣
- 리뷰 횟수: ✅
풀이 키워드
스포주의
완전탐색 bfs
풀이 코드
정보
- 메모리: 45420 KB
- 시간: 535 ms
class Solution {
String s;
int k;
boolean hasK(String ss) { // ss: subsequence
int i = 0; // index of ss
int cnt = 0; // count of ss appearance in s
char[] ssArr = ss.toCharArray();
for (char ch : s.toCharArray()) {
if (ch == ssArr[i]) {
++i;
if (i >= ssArr.length) {
i = 0;
++cnt;
if (cnt == k) return true;
}
}
}
return false;
}
public String longestSubsequenceRepeatedK(String s, int k) {
this.s = s;
this.k = k;
String ans = "";
Deque<String> dq = new ArrayDeque<>();
dq.add("");
while (!dq.isEmpty()) {
String cand = dq.poll();
for (char ch = 'a'; ch <= 'z'; ++ch) {
String nCand = cand + ch;
if (hasK(nCand)) {
ans = nCand;
dq.add(nCand);
}
}
}
return ans;
}
}
풀이 해설
문자열 s에서 k번 등장하는 subsequence를 구하는 문제이다. (substring 아님)
경우의 수가 상당히 우려되지만 문제의 제약 조건이 아주 절묘하게 설정되어 있어서,
bfs로 완탐을 돌려도 TLE가 발생하지 않는다(!)
bfs로 level-by-level traversal을 수행하면 되는데, 다만 시간복잡도 계산 면에서 좀 부조리한 느낌이 있다.
✏️ 문제 구조화하기
발상을 이런식으로 가야 한다.
- subsequence 문자열
ss의 등장 빈도가k인지 계산하는 로직 구상 ss를 구성하는 로직 구상
1번은 풀이에서의 hasK 함수 로직에 해당하고, 비교적 발상하기 쉽다.
그러나 2번에서 이리저리 최적화 기법을 생각하다보면 꽤나 시간이 흐르게 된다.
그 이유는 정답이 최대 길이의, lex-largest 해야 한다는 조건이 있기 때문이다.
이렇게 순회할까?
for: z -> a 순으로 순회
for: 최대길이 ~ 최소길이 순으로 순회
맨 처음엔 상단의 방식으로 순회하는 것을 고민해보았는데, 의미가 없다.
z일때 길이 x인 후보를 찾았는데, 그 다음 순회인 y에서 x+1 길이의 후보를 찾을 수도 있기 때문이다.
그럼 요거는?
for: 최대길이 ~ 최소길이 순으로 순회
for: z -> a 순으로 순회
아 그럼 이렇게 하면 되겠네! 싶어 두번째 발상으로 시도해보지만, 코드 짜보면 z -> a 순회 부분에서 막힌다.
z로 시작하는 최대 길이 문자열로 init해야 하고, 순회하면서 하나씩 잘라 다른 문자 붙여야 하고... 이게 맞나 싶어진다.
그래서 결국엔 완탐으로 회ㅋ귀ㅋ... 하게 되는데
여기서 시간복잡도가 걱정되기 시작한다.