LCS관련 백준문제를 참고 하자.
재귀풀이
memoize 하지 않으면 O(2^n)복잡도라 n이 20 이상일 경우 TLE 나기 쉽다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | #include <bits/stdc++.h> using namespace std; char s1[1001],s2[1001]; int lcs(char* s1, char* s2) { if(*s1==0 || *s2==0) return 0; if(*s1==*s2) return 1+lcs(s1+1, s2+1); return max(lcs(s1+1,s2),lcs(s1,s2+1)); } int main(void) { scanf("%s %s", s1, s2); printf("%d\n",lcs(s1,s2)); return 0; } | cs |
재귀+Memoization = (Recursive DP)
위의 소스코드에 memoize만 추가해준 코드로 왠만한 문제는 이정도 선에서 푸는게 가장 쉽다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | char s1[1001],s2[1001]; int n1, n2; int dp[1001][1001]; int lcs(int i, int j) { if(i==n1 || j==n2) return 0; if(dp[i][j]) return dp[i][j]; if(s1[i]==s2[j]) return dp[i][j] = 1 + lcs(i+1, j+1); return dp[i][j] = max(lcs(i+1,j), lcs(i,j+1)); } int main(void) { scanf("%s %s", s1, s2); n1 = strlen(s1), n2 = strlen(s2); printf("%d\n", lcs(0,0)); return 0; } | cs |
iterative DP
for문으로 푸는 것에 관심있다면, 조금 덜 직관적일 수 있으며, 아래처럼
dp[i][j] = i,j번째 문자열까지의 lcs 로 놓고.. 테이블을 그려놓고 규칙을 발견해서 푸는게 좋다.
숫자가 증가하는 모서리 부분을 보면 dp[i][j] = 1 + dp[i-1][j-1] 규칙을 찾을 수 있고,
숫자가 증가하는 모서리가 아닌 기타 부분을 보면 dp[i][j] = max(dp[i][j-1], dp[i-1][j]) 규칙을 찾을 수 있다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | #include <bits/stdc++.h> using namespace std; char s1[1001],s2[1001]; int n1, n2; int dp[1001][1001]; int main(void) { scanf("%s %s", s1, s2); n1 = strlen(s1), n2 = strlen(s2); dp[0][0] = s1[0]==s2[0]; for(int i=1;i<n1;i++) dp[i][0] = max(dp[i-1][0], int(s1[i]==s2[0])); for(int j=1;j<n2;j++) dp[0][j] = max(dp[0][j-1], int(s1[0]==s2[j])); for(int i=1;i<n1;i++){ for(int j=1;j<n2;j++){ if(s1[i]==s2[j]) dp[i][j] = 1 + dp[i-1][j-1]; else dp[i][j] = max(dp[i-1][j],dp[i][j-1]); } } printf("%d\n", dp[n1-1][n2-1]); return 0; } | cs |
반응형
'Programming > Algorithm' 카테고리의 다른 글
약수 출력하기 (0) | 2019.03.24 |
---|---|
우선순위 큐(priority queue) (0) | 2019.03.24 |
이항계수( binomial coefficient), 조합(combination) (0) | 2019.03.14 |
유클리드 호제법(최대공약수, GCD 구하기) (0) | 2019.03.14 |
[algorithm] subset sum (0) | 2017.11.20 |