Skip to content

Commit 0e73afc

Browse files
committed
- 8주차 문제 풀이
1 parent e2840cc commit 0e73afc

File tree

1 file changed

+77
-22
lines changed

1 file changed

+77
-22
lines changed

longest-common-subsequence/Geegong.java

Lines changed: 77 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -20,36 +20,91 @@ public class Geegong {
2020
* @return
2121
*/
2222
public int longestCommonSubsequence(String text1, String text2) {
23-
char[] chText1 = text1.toCharArray();
24-
char[] chText2 = text2.toCharArray();
25-
26-
// text1만 각 원소 별로 char가 가지는 index를 array 로 갖는 배열을 생성
27-
List<Integer>[] positionIndices = new List[26];
28-
for (int index = 0; index<chText1.length; index++) {
29-
if (positionIndices[chText1[index] - 'a'] == null) {
30-
positionIndices[chText1[index] - 'a'] = new ArrayList();
31-
positionIndices[chText1[index] - 'a'].add(index);
32-
} else {
33-
positionIndices[chText1[index] - 'a'].add(index);
34-
}
23+
24+
/**
25+
* DP 를 이용한 LIS 구하기
26+
* 2차원 배열을 만들어 text1, text2 들을 하나씩 훑어가며
27+
* 이전에 일치했던 각 character 별로 횟수들을 기록해가며 더 LIS 로 붙일 수 있는지 정리해가는 기법
28+
* 참고 블로그 : https://velog.io/@emplam27/%EC%95%8C%EA%B3%A0%EB%A6%AC%EC%A6%98-%EA%B7%B8%EB%A6%BC%EC%9C%BC%EB%A1%9C-%EC%95%8C%EC%95%84%EB%B3%B4%EB%8A%94-LCS-%EC%95%8C%EA%B3%A0%EB%A6%AC%EC%A6%98-Longest-Common-Substring%EC%99%80-Longest-Common-Subsequence
29+
* time complexity : O(M * N) => O (N)
30+
* space complexity : O(M * N) => O (N)
31+
*/
32+
char[] ch1 = text1.toCharArray();
33+
char[] ch2 = text2.toCharArray();
34+
35+
int[][] LISArr = new int[ch1.length + 1][ch2.length + 1];
36+
37+
// first, fill zeros in first row, first column for convenient
38+
for (int idx=0; idx<=ch2.length; idx++) {
39+
LISArr[0][idx] = 0;
3540
}
3641

42+
for (int idx=0; idx<=ch1.length; idx++) {
43+
LISArr[idx][0] = 0;
44+
}
3745

38-
// 여기서부터 LIS 를 구할것임
39-
List<Integer> indices = new ArrayList<>();
40-
for (int index=0; index<chText2.length; index++) {
46+
int maxLIS = 0;
47+
for (int index1 = 0; index1<ch1.length; index1++) {
48+
for (int index2 = 0; index2<ch2.length; index2++) {
4149

42-
char find = chText2[index];
43-
if (positionIndices[find-'a'] != null && positionIndices[find-'a'].size() > 0) {
44-
// 역순 (LIS 를 구하기 위해서 일부러 뒤집어 높음, 즉 각 char 별 LIS 를 구할것이기 때문에..)
45-
// positionIndices 에서 구했던 값들을 그대로 addAll 한다면 오름차순이 되기때문에 정확한 LIS 를 구할 수 없다
50+
// if same, then
51+
if (ch1[index1] == ch2[index2]) {
52+
// LISArr 의 인덱스값이 +1 이 되는 이유는 LISArr 의 크기가 text1, text2 크기 + 1 만큼 만들었기 때문
53+
LISArr[index1 + 1][index2 + 1] = LISArr[index1][index2] + 1;
54+
} else {
55+
int biggerOne = Math.max(LISArr[index1][index2 + 1], LISArr[index1 + 1][index2]);
56+
LISArr[index1 + 1][index2 + 1] = biggerOne;
57+
}
4658

47-
indices.addAll(positionIndices[find-'a'].stream().sorted(Comparator.reverseOrder()).toList());
59+
maxLIS = Math.max(maxLIS, LISArr[index1 + 1][index2 + 1]);
4860
}
4961
}
5062

51-
// find LIS
52-
return findLIS(indices).size();
63+
return maxLIS;
64+
65+
66+
67+
/**
68+
* LIS, LCS 와 연관지어서 풀이
69+
* 1. 먼저 text1을 훑어보는데 text1에 중복되는 알파벳이 있을 수 있기에 각 캐릭터별로 인덱스들을 저장 (각 원소가 arrayList가 있는 배열)
70+
* 2. text2 를 훑으면서 매칭되는 캐릭터들에 대해서만 1에서 저장된 인덱스들을 한 배열안에 나열
71+
* -> 이떄 나열해서 넣을때마다 역순으로 집어넣는게 중요! (왜냐면 이 나열된 인덱스들을 가지고 LIS를 구할거라서)
72+
* 3. 나열된 인덱스들의 값들을 가지고 LIS 를 구한다, 즉 이 LIS의 길이가 LCS 의 길이가 된다..!! (와우 신기)
73+
* 그러나 leet code 에 돌렸을 때 runtime 이 영 좋지는 않음
74+
*
75+
* time complexity : O(M + N logN) => text2에 대해서 문자마다 바이너리서치가 수행됨
76+
* space complexity : O(M+N)
77+
*/
78+
// char[] chText1 = text1.toCharArray();
79+
// char[] chText2 = text2.toCharArray();
80+
//
81+
// // text1만 각 원소 별로 char가 가지는 index를 array 로 갖는 배열을 생성
82+
// List<Integer>[] positionIndices = new List[26];
83+
// for (int index = 0; index<chText1.length; index++) {
84+
// if (positionIndices[chText1[index] - 'a'] == null) {
85+
// positionIndices[chText1[index] - 'a'] = new ArrayList();
86+
// positionIndices[chText1[index] - 'a'].add(index);
87+
// } else {
88+
// positionIndices[chText1[index] - 'a'].add(index);
89+
// }
90+
// }
91+
//
92+
//
93+
// // 여기서부터 LIS 를 구할것임
94+
// List<Integer> indices = new ArrayList<>();
95+
// for (int index=0; index<chText2.length; index++) {
96+
//
97+
// char find = chText2[index];
98+
// if (positionIndices[find-'a'] != null && positionIndices[find-'a'].size() > 0) {
99+
// // 역순 (LIS 를 구하기 위해서 일부러 뒤집어 높음, 즉 각 char 별 LIS 를 구할것이기 때문에..)
100+
// // positionIndices 에서 구했던 값들을 그대로 addAll 한다면 오름차순이 되기때문에 정확한 LIS 를 구할 수 없다
101+
//
102+
// indices.addAll(positionIndices[find-'a'].stream().sorted(Comparator.reverseOrder()).toList());
103+
// }
104+
// }
105+
//
106+
// // find LIS
107+
// return findLIS(indices).size();
53108
}
54109

55110
public List<Integer> findLIS(List<Integer> source) {

0 commit comments

Comments
 (0)