[JAVA 문제 풀이] 357. Find the Original Typed String II [원본 타이핑 문자열 II 찾기]
Jul 02, 2025
Contents
내가 작성한 코드 + 다른 사람의 코

앨리스는 컴퓨터에 특정 문자열을 입력하려고 시도하고 있습니다.
하지만 그녀는 서투른 경향이 있고 키를 너무 오래 눌러 문자를 여러 번 입력할 수 있습니다.
앨리스 화면에 표시되는 최종 출력을 나타내는 문자열 단어가 주어집니다.
또한 양의 정수 k도 주어집니다.
앨리스가 최소한 k 이상의 크기의 문자열을 입력하려고 했다면,
입력하려고 했을 가능성이 있는 원래 문자열의 총 개수를 반환하세요.
답이 매우 클 수 있으므로 모듈로 10^9 + 7로 반환하세요.
내가 작성한 코드 + 다른 사람의 코
import java.util.*;
class Solution {
private static final long MOD = (long) 1e9 + 7;
public int possibleStringCount(String word, int k) {
List<Integer> list = new ArrayList<>();
int n = word.length();
int i = 0;
// 1. word를 같은 문자가 연속된 블록 단위로 나누어 각 블록의 길이를 저장
// 예: word = "aabbccdd" → list = [2,2,2,2]
while (i < n) {
int j = i + 1;
while (j < n && word.charAt(j) == word.charAt(j - 1))
j++;
list.add(j - i);
i = j;
}
int m = list.size(); // 문자 블록 수
// 2. 뒤에서부터 가능한 경우 수를 누적 곱으로 저장
// power[i] = list[i] * list[i+1] * ... * list[m-1] (mod MOD)
long[] power = new long[m];
power[m - 1] = list.get(m - 1);
for (i = m - 2; i >= 0; i--) {
power[i] = (power[i + 1] * list.get(i)) % MOD;
}
// 3. 만약 블록 수 ≥ k → 이미 최소 길이가 k 이상이므로 가능한 조합 모두 유효
if (m >= k)
return (int) power[0]; // 모든 블록마다 하나만 고르면 최소 길이 m ≥ k
// 4. DP 시작: dp[i][j] = i번째 블록부터 고려할 때 추가로 j만큼 길이를 더 채우는 경우의 수
// 총 길이는 m(블록 개수) + j가 됨 → 이게 k 이상이면 OK
long[][] dp = new long[m][k - m + 1];
// 5. 마지막 블록에 대한 초기화
// j: 남은 추가 길이 (k - m)
// dp[m-1][j]: 마지막 블록에서 (블록 길이 - 줄여야 하는 양) 만큼 유효
for (i = 0; i < k - m + 1; i++) {
if (list.get(m - 1) + i + m > k)
dp[m - 1][i] = list.get(m - 1) - (k - m - i);
}
// 6. 뒤에서부터 DP 계산 (Bottom-up)
for (i = m - 2; i >= 0; i--) {
long sum = (dp[i + 1][k - m] * list.get(i)) % MOD; // j = k - m 에 대한 초기화
for (int j = k - m; j >= 0; j--) {
// 누적합 방식으로 dp[i][j] 계산
sum += dp[i + 1][j];
// sum에서 범위 초과된 dp 값을 제거
if (j + list.get(i) > k - m)
sum = (sum - dp[i + 1][k - m] + MOD) % MOD;
else
sum = (sum - dp[i + 1][j + list.get(i)] + MOD) % MOD;
// 현재 블록 길이만큼 곱해서 dp 저장
dp[i][j] = sum;
}
}
// 최종 결과는 첫 번째 블록부터 시작해서 전체 길이 k를 만드는 경우
return (int) dp[0][0];
}
}
Share article