1143.Β Longest Common Subsequence

  • 두 λ¬Έμžμ—΄ text1, text2의 κ°€μž₯ κΈ΄ 곡톡 λΆ€λΆ„ λ°°μ—΄μ˜ 길이λ₯Ό κ΅¬ν•œλ‹€.
  • 두 λ¬Έμžμ—΄μ„ λ™μ‹œμ— νƒμƒ‰ν•˜λ©΄μ„œ νŠΉμ • μœ„μΉ˜ i, j의 문자λ₯Ό λΆ€λΆ„ 배열에 포함 μ‹œν‚¨λ‹€. 이 λ•Œ μ–‘μͺ½μ˜ λ¬Έμžμ—΄μ΄ 같은지 ν™•μΈν•œλ‹€.
    • λ§Œμ•½ ν˜„μž¬ μœ„μΉ˜μ˜ λ¬Έμžμ—΄μ΄ κ°™λ‹€λ©΄ μ–‘μͺ½μ˜ μœ„μΉ˜λ₯Ό λ˜‘κ°™μ΄ 1 μ”© 증가 μ‹œν‚¨λ‹€. κ³΅ν†΅λ˜λŠ” λΆ€λΆ„ λ°°μ—΄μ˜ κΈΈμ΄λŠ” λ§ˆμ°¬κ°€μ§€λ‘œ 1 μ¦κ°€ν•œλ‹€.
    • λ§Œμ•½ ν˜„μž¬ μœ„μΉ˜μ˜ λ¬Έμžμ—΄μ΄ κ°™μ§€ μ•Šλ‹€λ©΄ 첫번째 λ¬Έμžμ—΄μ˜ μœ„μΉ˜ i λ˜λŠ” λ‘λ²ˆμ§Έ λ¬Έμžμ—΄μ˜ μœ„μΉ˜ jλ₯Ό 1 μ¦κ°€μ‹œν‚¨λ‹€. 두 경우 쀑에 더 κΈ΄ 곡톡 λΆ€λΆ„ 배열을 κ°€μ§„ 것을 μ΅œμ’… κ°’μœΌλ‘œ ν•œλ‹€.
    • μ–‘μͺ½μ˜ 문자λ₯Ό νƒμƒ‰ν•˜λŠ” μœ„μΉ˜ (i, j) λ³„λ‘œ 곡톡 λΆ€λΆ„ λ°°μ—΄μ˜ μ΅œλŒ€ κΈΈμ΄λŠ” 항상 λ™μΌν•˜κ²Œ κ³„μ‚°λ˜λ―€λ‘œ memoization을 ν™œμš©ν•œλ‹€.
  • μœ„μ—μ„œ μ„€λͺ…ν•œ 방식을 κ·ΈλŒ€λ‘œ κ΅¬ν˜„ν•˜λ©΄ μ•„λž˜μ™€ κ°™λ‹€. ν†΅κ³ΌλŠ” λ˜κΈ°λŠ” ν•˜λŠ”λ° μ‹€ν–‰ 속도가 λŠλ¦¬λ‹€ (61 ms).
class Solution { int traverse(String text1, String text2, int[][] dp, int i, int j) { if (i >= text1.length() || j >= text2.length()) { return 0; } if (dp[i][j] != -1) return dp[i][j]; boolean isSameChar = text1.charAt(i) == text2.charAt(j); return dp[i][j] = Math.max( traverse(text1, text2, dp, i + 1, j + 1) + (isSameChar? 1 : 0), Math.max( traverse(text1, text2, dp, i + 1, j), traverse(text1, text2, dp, i, j + 1) ) ); } public int longestCommonSubsequence(String text1, String text2) { int[][] dp = new int[text1.length()][text2.length()]; for (int[] sub : dp) { Arrays.fill(sub, -1); } return traverse(text1, text2, dp, 0, 0); } }
  • 같은 λ‘œμ§μ„ for loop둜 κ΅¬ν˜„ν•  수 μžˆλ‹€.
    • νŽΈμ˜μƒ memoization λ°°μ—΄ dp의 크기λ₯Ό 1 더 크게 μž‘λŠ”λ‹€.
    • ν˜„μž¬ index κ°’ (i, j)을 κΈ°μ€€μœΌλ‘œ 이전 μœ„μΉ˜ (i - 1, j - 1)의 값을 λΉ„κ΅ν•œλ‹€.
      • λ§Œμ•½ 0λΆ€ν„° μ‹œμž‘ν•˜λŠ” indexλ₯Ό μ‚¬μš©ν•˜κ²Œ 되면 i, j 값이 0보닀 큰지 맀번 확인해야 λ˜λŠ” λ²ˆκ±°λ‘œμ›€μ΄ μžˆλ‹€.
    • λΉ„κ΅ν•œ μ–‘μͺ½ λ¬Έμžκ°€ λ™μΌν•˜λ©΄ μ–‘μͺ½ λͺ¨λ‘ indexλ₯Ό 1μ”© 증가 μ‹œν‚€λŠ” κ²ƒμ΄λ―€λ‘œ 이전 index의 κ²°κ³Όκ°’ dp[i - 1][j - 1]에 1을 λ”ν•œ 것이 ν˜„μž¬ index의 κ²°κ³Όκ°’ dp[i][j]이 λœλ‹€.
    • λΉ„κ΅ν•œ μ–‘μͺ½ λ¬Έμžκ°€ λ™μΌν•˜μ§€ μ•ŠμœΌλ©΄ μ–΄λŠ ν•œμͺ½μ˜ indexλ₯Ό 1 μ¦κ°€μ‹œν‚€λŠ” κ²ƒμ΄λ―€λ‘œ 각각의 이전 index의 κ²°κ³Όκ°’λ“€ dp[i - 1][j], dp[i][j - 1] 쀑 큰 값을 ν˜„μž¬ index의 κ²°κ³Ό dp[i][j]둜 ν•œλ‹€.
    • μ΅œμ’… κ²°κ³Ό 값은 μ–‘μͺ½ λͺ¨λ‘μ˜ λ§ˆμ§€λ§‰ index μœ„μΉ˜μ˜ κ²°κ³Όκ°’dp[m][n]으둜 ν•œλ‹€.
class Solution { public int longestCommonSubsequence(String text1, String text2) { int m = text1.length(), n = text2.length(); int[][] dp = new int[m + 1][n + 1]; for (int i = 1; i <= m; ++i) { for (int j = 1; j <= n; ++j) { if (text1.charAt(i - 1) == text2.charAt(j - 1)) { dp[i][j] = dp[i - 1][j - 1] + 1; } else { dp[i][j] = Math.max(dp[i - 1][j], dp[i][j - 1]); } } } return dp[m][n]; } }
Β