{"componentChunkName":"component---src-templates-blog-post-js","path":"/Algorithm-Analysis/2020-04-01-알고리즘-최장공통부분수열(LCS)/","result":{"data":{"site":{"siteMetadata":{"title":"Hun's Footsteps 🥷","author":"전여훈","siteUrl":"https://jeonyeohun.netlify.app","comment":{"disqusShortName":"","utterances":"jeonyeohun/jeonyeohun.github.io"},"sponsor":{"buyMeACoffeeId":"jeonyeohun"}}},"markdownRemark":{"id":"21933986-797d-52ae-ade9-02fe4e328d5c","excerpt":"Logest Common Subequence 우리 말로 최장 공통 부분 수열이라고도 불리는 알고리즘이다. 어떤 문자열이 두 개 있을 때, 두 수열 사이에 있는 공통적인 문자들의 가장 긴 조합을 찾는 문제이다. 예를 들어 다음 두 문자열이 있다고 하자. 두 문자열의 사이에는 많은 부분 문자열들이 있는데, 문자가 하나 뿐인 부분 문자열을 제외하고 모두 나열해보면 다음과 같다: 이 중에서 가장긴 부분 문자열은 B,D,A,B가 될 것이다. Brute-Force…","html":"<h1 id=\"logest-common-subequence\" style=\"position:relative;\"><a href=\"#logest-common-subequence\" aria-label=\"logest common subequence permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Logest Common Subequence</h1>\n<p>우리 말로 최장 공통 부분 수열이라고도 불리는 알고리즘이다. 어떤 문자열이 두 개 있을 때, 두 수열 사이에 있는 공통적인 문자들의 가장 긴 조합을 찾는 문제이다. 예를 들어 다음 두 문자열이 있다고 하자.</p>\n<center>\nX = (A, B, C, B, D, A, B)<br>\nY = (B, D, C, A, B, A)\n</center><br>\n<p>두 문자열의 사이에는 많은 부분 문자열들이 있는데, 문자가 하나 뿐인 부분 문자열을 제외하고 모두 나열해보면 다음과 같다:</p>\n<center>\nA, B<br>\nA, B, A<br>\nB, C<br>\nB, C, B<br>\nC, B<br>\nC, B, A<br>\nB, D<br>\nB, D, A<br>\nB, D, A, B<br>\n</center><br>\n<p>이 중에서 가장긴 부분 문자열은 B,D,A,B가 될 것이다.</p>\n<h2 id=\"brute-force\" style=\"position:relative;\"><a href=\"#brute-force\" aria-label=\"brute force permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Brute-Force</h2>\n<p>이 문제를 해결하기 위해서 먼저 브루트 포스로 모든 경우의 수를 따져보는 것을 고려해보자. 우리에게 두 개의 문자열 X[1…m] 과 Y[1…n] 가 있다고 해보자. 모든 경우의 수를 다 시도해보려면, X에 있는 모든 부분 문자열을 구해서 Y에 대입해보면 된다. 따라서 브루트 포스로 이 문제를 해결하는 속도는,</p>\n<ol>\n<li>m 개의 문자로 이루어진 문자열 X에서 모든 부분 문자열을 만들 때 걸리는 속도 2<sup>m</sup>.</li>\n<li>위에서 구한 부분수열을 Y에 대입해볼 때 소요되는 속도 O(n).</li>\n</ol>\n<p>두 연산 시간의 합이 되고 최악의 경우를 고려했을 때, O(n2<sup>m</sup>) 으로 표현할 수 있다. 따라서 m의 갯수에 따라 엄청난 시간이 걸릴 수 있기 때문에 브루트 포스는 이 문제를 해결하는데 적합한 접근이 아니다.</p>\n<h2 id=\"dynamic-programming\" style=\"position:relative;\"><a href=\"#dynamic-programming\" aria-label=\"dynamic programming permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Dynamic Programming</h2>\n<h3 id=\"step-1--optimal-substructure\" style=\"position:relative;\"><a href=\"#step-1--optimal-substructure\" aria-label=\"step 1  optimal substructure permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Step 1 : Optimal Substructure</h3>\n<p>문제를 일반화하기 위해서 비교해야하는 문자열을 X=&#x3C;x<sub>1</sub>, x<sub>2</sub>, … , x<sub>m</sub>>, Y=&#x3C;y<sub>1</sub>, y<sub>2</sub>, … , y<sub>n</sub>> 라고 하고, 두 문자열의 LCS를 Z=&#x3C;z<sub>1</sub>, z<sub>2</sub>, … , z<sub>k</sub>> 라고 해보자. 그렇다면 우리는 다음과 같은 명제가 성립한다고 할 수 있을 것이다.</p>\n<ol>\n<li>x<sub>m</sub> = y<sub>n</sub> 이라면, x<sub>m</sub> = y<sub>n</sub> = z<sub>k</sub> 이고 새로운 LCS 는 X<sub>m-1</sub> 와 Y<sub>n-1</sub> 이라고 할 수 있다.</li>\n<li>수식이 헷갈릴 수도 있는데, 매우 당연한 이야기를 수학적으로 표현한 것이다. 두 문자열의 가장 끝 문자가 서로 같다면, LCS의 가장 끝이 해당 문자로 끝나는 것은 너무나 자명하지 않은가?</li>\n<li>x<sub>m</sub> ≠ y<sub>n</sub> 이라면, x<sub>m</sub> ≠ z<sub>k</sub> 이고 새로운 LCS 는 X<sub>m-1</sub> 와 Y 이라고 할 수 있다.</li>\n<li>x<sub>m</sub> ≠ y<sub>n</sub> 이라면, y<sub>n</sub> ≠ z<sub>k</sub> 이고 새로운 LCS 는 X 와 Y<sub>n-1</sub> 이라고 할 수 있다.</li>\n<li>만약 두 문자가 다르다고 한다면, 우리는 두 가지 경우를 생각할 수 있다. X 문자열의 길이를 줄이거나, Y 문자열의 길이를 줄이는 것이다.\n우리가 구하고자 하는 것은 가장 긴 부분 문자열을 구성하게되는 조합이기 때문에 두 경우 중에서 더 큰 부분 문자열을 만드는 쪽을 선택해야 할 것이다.</li>\n</ol>\n<h3 id=\"step-2--recursive-solution\" style=\"position:relative;\"><a href=\"#step-2--recursive-solution\" aria-label=\"step 2  recursive solution permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Step 2 : Recursive Solution</h3>\n<p>위 논리가 꽤나 타당하고 생각이 든다. 그렇다면 수식으로 만들어보자.</p>\n<p><img src=\"https://www.thecrazyprogrammer.com/wp-content/uploads/2015/05/Longest-Common-Subsequece-Problem.png\"></p>\n<p>c[i, j] 가 i, j 사이의 최대 부분 문자열의 길이를 가지고 있다고 한다면, X 와 Y 의 문자가 같을 때, 바로 이전 최장 문자열의 길이에 1을 더한 값을 새로 저장하고, 두 문자가 다를 때는 X쪽 최장 문자열의 길이와 Y쪽 최장 문자열의 길이를 비교해서 더 큰 값을 가져온다.</p>\n<p>그런데 위 계산식 대로 진행하면, 우리는 결국 똑같은 연산을 계속해서 해야하는 상황을 맞이한다. 그리고 이런 상황은 연산 시간을 낭비하게 한다. 따라서 우리는 한번 계산한 결과를 테이블에 저장해두고 재사용하는 방식을 시도해야한다.</p>\n<h3 id=\"step-3--computing-the-optimal-costs\" style=\"position:relative;\"><a href=\"#step-3--computing-the-optimal-costs\" aria-label=\"step 3  computing the optimal costs permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Step 3 : Computing the Optimal Costs</h3>\n<p>이미 계산한 값을 재사용하기 위해서 2차원 배열을 통해 테이블을 만들어 이 문제를 풀어보자.</p>\n<table>\n<thead>\n<tr>\n<th>Y\\X</th>\n<th>0</th>\n<th>A</th>\n<th>B</th>\n<th>C</th>\n<th>B</th>\n<th>D</th>\n<th>A</th>\n<th>B</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>0</td>\n<td></td>\n<td></td>\n<td></td>\n<td></td>\n<td></td>\n<td></td>\n<td></td>\n<td></td>\n</tr>\n<tr>\n<td>B</td>\n<td></td>\n<td></td>\n<td></td>\n<td></td>\n<td></td>\n<td></td>\n<td></td>\n<td></td>\n</tr>\n<tr>\n<td>D</td>\n<td></td>\n<td></td>\n<td></td>\n<td></td>\n<td></td>\n<td></td>\n<td></td>\n<td></td>\n</tr>\n<tr>\n<td>C</td>\n<td></td>\n<td></td>\n<td></td>\n<td></td>\n<td></td>\n<td></td>\n<td></td>\n<td></td>\n</tr>\n<tr>\n<td>A</td>\n<td></td>\n<td></td>\n<td></td>\n<td></td>\n<td></td>\n<td></td>\n<td></td>\n<td></td>\n</tr>\n<tr>\n<td>B</td>\n<td></td>\n<td></td>\n<td></td>\n<td></td>\n<td></td>\n<td></td>\n<td></td>\n<td></td>\n</tr>\n<tr>\n<td>A</td>\n<td></td>\n<td></td>\n<td></td>\n<td></td>\n<td></td>\n<td></td>\n<td></td>\n<td></td>\n</tr>\n</tbody>\n</table>\n<p>위와 같이 테이블을 세팅하자. 그리고 모든 X의 문자에 대해서 Y의 문자를 꺼내와 비교해서 위에서 작성했던 수식에 따라 값을 채워 넣자. 첫 몇 개를 진행해보면,</p>\n<table>\n<thead>\n<tr>\n<th>Y\\X</th>\n<th>0</th>\n<th>A</th>\n<th>B</th>\n<th>C</th>\n<th>B</th>\n<th>D</th>\n<th>A</th>\n<th>B</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>0</td>\n<td>0</td>\n<td>0</td>\n<td>0</td>\n<td>0</td>\n<td>0</td>\n<td>0</td>\n<td>0</td>\n<td>0</td>\n</tr>\n<tr>\n<td>B</td>\n<td>0</td>\n<td>0</td>\n<td>1</td>\n<td>1</td>\n<td>1</td>\n<td>1</td>\n<td>1</td>\n<td>1</td>\n</tr>\n<tr>\n<td>D</td>\n<td>0</td>\n<td></td>\n<td></td>\n<td></td>\n<td></td>\n<td></td>\n<td></td>\n<td></td>\n</tr>\n<tr>\n<td>C</td>\n<td>0</td>\n<td></td>\n<td></td>\n<td></td>\n<td></td>\n<td></td>\n<td></td>\n<td></td>\n</tr>\n<tr>\n<td>A</td>\n<td>0</td>\n<td></td>\n<td></td>\n<td></td>\n<td></td>\n<td></td>\n<td></td>\n<td></td>\n</tr>\n<tr>\n<td>B</td>\n<td>0</td>\n<td></td>\n<td></td>\n<td></td>\n<td></td>\n<td></td>\n<td></td>\n<td></td>\n</tr>\n<tr>\n<td>A</td>\n<td>0</td>\n<td></td>\n<td></td>\n<td></td>\n<td></td>\n<td></td>\n<td></td>\n<td></td>\n</tr>\n</tbody>\n</table>\n<p>B에 대한 행은 다음과 같이 채울 수 있다. A를 만났을 때는 이전 값 중에 제일 큰 0을 넣어주었다. 그리고 B를 만나게 되면 X<sub>i</sub> 와 Y<sub>j</sub> 의 값이 같기 때문에 이전 위치의 가장 긴 길이인 0에 1을 더해 1로 채워주고 있다. C를 체크해보면 B와 C는 다른 값이기 때문에, X를 제외 했을 때, 즉 바로 왼쪽에 있는 값과, Y를 제외했을 때, 즉 좌측 대각선 위에 있는 값 중에 더 큰 값으로 배열을 채워주게 된다. 이 논리대로 테이블을 모두 채워나가면 다음과 같이 표를 완성시킬 수 있다.</p>\n<table>\n<thead>\n<tr>\n<th>Y\\X</th>\n<th>0</th>\n<th>A</th>\n<th>B</th>\n<th>C</th>\n<th>B</th>\n<th>D</th>\n<th>A</th>\n<th>B</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>0</td>\n<td>0</td>\n<td>0</td>\n<td>0</td>\n<td>0</td>\n<td>0</td>\n<td>0</td>\n<td>0</td>\n<td>0</td>\n</tr>\n<tr>\n<td>B</td>\n<td>0</td>\n<td>0</td>\n<td>1</td>\n<td>1</td>\n<td>1</td>\n<td>1</td>\n<td>1</td>\n<td>1</td>\n</tr>\n<tr>\n<td>D</td>\n<td>0</td>\n<td>0</td>\n<td>1</td>\n<td>1</td>\n<td>1</td>\n<td>2</td>\n<td>2</td>\n<td>2</td>\n</tr>\n<tr>\n<td>C</td>\n<td>0</td>\n<td>0</td>\n<td>1</td>\n<td>2</td>\n<td>2</td>\n<td>2</td>\n<td>2</td>\n<td>2</td>\n</tr>\n<tr>\n<td>A</td>\n<td>0</td>\n<td>1</td>\n<td>1</td>\n<td>2</td>\n<td>2</td>\n<td>2</td>\n<td>3</td>\n<td>3</td>\n</tr>\n<tr>\n<td>B</td>\n<td>0</td>\n<td>1</td>\n<td>2</td>\n<td>2</td>\n<td>3</td>\n<td>3</td>\n<td>3</td>\n<td>4</td>\n</tr>\n<tr>\n<td>A</td>\n<td>0</td>\n<td>1</td>\n<td>2</td>\n<td>2</td>\n<td>3</td>\n<td>3</td>\n<td>4</td>\n<td>4</td>\n</tr>\n</tbody>\n</table>\n<p>위 표에서 확인할 수 있는 것 처럼 우리가 얻을 수 있는 LCS의 길이는 4이고, 해당 길이로 조합할 수 있는 부분 문자열은 총 3종류가 된다. 왜냐하면 LCS는 여러개가 나올 수 있고 표에서 최대 값을 가지는 아이템의 갯수가 그 경우의 수를 의미하기 때문이다. 위와 같은 알고리즘으로 계산을 진행하게 되면, 우리는 LCS를 단순히 표의 모든 위치를 순회하는 것을 통해 알 수 있기 때문에, 연산 속도는 𝛩(mn) 으로 표현할 수 있다.</p>\n<p>위 표를 기준으로 LCS인 서브스트링을 얻으려면 LCS 값을 가지고 있는 아이템 위치부터 왼쪽으로 이동하면서, X와 Y가 같은 알파벳들을 기록해주면 된다. 여러 문자열이 나올 수 있지만 하나를 예로 들어보면, B -> A -> D -> B 의 역순으로 나열한 문자열인 BDAB 가 하나의 LCS가 될 것이다.</p>\n<h3 id=\"step-4-constructing-an-optimal-solution\" style=\"position:relative;\"><a href=\"#step-4-constructing-an-optimal-solution\" aria-label=\"step 4 constructing an optimal solution permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Step 4: Constructing an Optimal Solution</h3>\n<p>이제 코드로 구현해보자. LCS 문제는 꽤나 유명한 문제이기 때문에 [백준 알고리즘] 알고리즘에서 문제를 풀어볼 수 있었다.</p>\n<p>문제: <a href=\"https://www.acmicpc.net/problem/9251\">https://www.acmicpc.net/problem/9251</a></p>\n<div class=\"gatsby-highlight\" data-language=\"cpp\"><pre class=\"language-cpp\"><code class=\"language-cpp\"><span class=\"token macro property\"><span class=\"token directive-hash\">#</span><span class=\"token directive keyword\">include</span> <span class=\"token string\">&lt;iostream></span></span>\n<span class=\"token macro property\"><span class=\"token directive-hash\">#</span><span class=\"token directive keyword\">include</span> <span class=\"token string\">&lt;string></span></span>\n<span class=\"token macro property\"><span class=\"token directive-hash\">#</span><span class=\"token directive keyword\">include</span> <span class=\"token string\">&lt;algorithm></span></span>\n\n<span class=\"token keyword\">using</span> <span class=\"token keyword\">namespace</span> std<span class=\"token punctuation\">;</span>\n\n<span class=\"token keyword\">int</span> dp<span class=\"token punctuation\">[</span><span class=\"token number\">1001</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">[</span><span class=\"token number\">1001</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">;</span>\n\n<span class=\"token keyword\">int</span> <span class=\"token function\">main</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span>\n<span class=\"token punctuation\">{</span>\n    string s1<span class=\"token punctuation\">,</span> s2<span class=\"token punctuation\">;</span>\n\n    cin <span class=\"token operator\">>></span> s1 <span class=\"token operator\">>></span> s2<span class=\"token punctuation\">;</span>\n    <span class=\"token keyword\">int</span> lcs <span class=\"token operator\">=</span> <span class=\"token number\">0</span><span class=\"token punctuation\">;</span>\n\n    <span class=\"token keyword\">for</span> <span class=\"token punctuation\">(</span><span class=\"token keyword\">int</span> i <span class=\"token operator\">=</span> <span class=\"token number\">1</span><span class=\"token punctuation\">;</span> i <span class=\"token operator\">&lt;=</span> s2<span class=\"token punctuation\">.</span><span class=\"token function\">size</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span> i<span class=\"token operator\">++</span><span class=\"token punctuation\">)</span>\n    <span class=\"token punctuation\">{</span>\n        <span class=\"token keyword\">for</span> <span class=\"token punctuation\">(</span><span class=\"token keyword\">int</span> j <span class=\"token operator\">=</span> <span class=\"token number\">1</span><span class=\"token punctuation\">;</span> j <span class=\"token operator\">&lt;=</span> s1<span class=\"token punctuation\">.</span><span class=\"token function\">size</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span> j<span class=\"token operator\">++</span><span class=\"token punctuation\">)</span>\n        <span class=\"token punctuation\">{</span>\n            dp<span class=\"token punctuation\">[</span>i<span class=\"token punctuation\">]</span><span class=\"token punctuation\">[</span>j<span class=\"token punctuation\">]</span> <span class=\"token operator\">=</span> dp<span class=\"token punctuation\">[</span>i <span class=\"token operator\">-</span> <span class=\"token number\">1</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">[</span>j<span class=\"token punctuation\">]</span><span class=\"token punctuation\">;</span>\n            <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span>s2<span class=\"token punctuation\">[</span>i <span class=\"token operator\">-</span> <span class=\"token number\">1</span><span class=\"token punctuation\">]</span> <span class=\"token operator\">==</span> s1<span class=\"token punctuation\">[</span>j <span class=\"token operator\">-</span> <span class=\"token number\">1</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">)</span>\n            <span class=\"token punctuation\">{</span>\n                dp<span class=\"token punctuation\">[</span>i<span class=\"token punctuation\">]</span><span class=\"token punctuation\">[</span>j<span class=\"token punctuation\">]</span> <span class=\"token operator\">=</span> dp<span class=\"token punctuation\">[</span>i <span class=\"token operator\">-</span> <span class=\"token number\">1</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">[</span>j <span class=\"token operator\">-</span> <span class=\"token number\">1</span><span class=\"token punctuation\">]</span> <span class=\"token operator\">+</span> <span class=\"token number\">1</span><span class=\"token punctuation\">;</span>\n                lcs <span class=\"token operator\">=</span> <span class=\"token function\">max</span><span class=\"token punctuation\">(</span>lcs<span class=\"token punctuation\">,</span> dp<span class=\"token punctuation\">[</span>i<span class=\"token punctuation\">]</span><span class=\"token punctuation\">[</span>j<span class=\"token punctuation\">]</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n            <span class=\"token punctuation\">}</span>\n            <span class=\"token keyword\">else</span>\n            <span class=\"token punctuation\">{</span>\n                <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span>dp<span class=\"token punctuation\">[</span>i <span class=\"token operator\">-</span> <span class=\"token number\">1</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">[</span>j<span class=\"token punctuation\">]</span> <span class=\"token operator\">></span> dp<span class=\"token punctuation\">[</span>i<span class=\"token punctuation\">]</span><span class=\"token punctuation\">[</span>j <span class=\"token operator\">-</span> <span class=\"token number\">1</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">)</span>\n                    dp<span class=\"token punctuation\">[</span>i<span class=\"token punctuation\">]</span><span class=\"token punctuation\">[</span>j<span class=\"token punctuation\">]</span> <span class=\"token operator\">=</span> dp<span class=\"token punctuation\">[</span>i <span class=\"token operator\">-</span> <span class=\"token number\">1</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">[</span>j<span class=\"token punctuation\">]</span><span class=\"token punctuation\">;</span>\n                <span class=\"token keyword\">else</span>\n                    dp<span class=\"token punctuation\">[</span>i<span class=\"token punctuation\">]</span><span class=\"token punctuation\">[</span>j<span class=\"token punctuation\">]</span> <span class=\"token operator\">=</span> dp<span class=\"token punctuation\">[</span>i<span class=\"token punctuation\">]</span><span class=\"token punctuation\">[</span>j <span class=\"token operator\">-</span> <span class=\"token number\">1</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">;</span>\n            <span class=\"token punctuation\">}</span>\n        <span class=\"token punctuation\">}</span>\n    <span class=\"token punctuation\">}</span>\n\n    cout <span class=\"token operator\">&lt;&lt;</span> lcs<span class=\"token punctuation\">;</span>\n    <span class=\"token keyword\">return</span> <span class=\"token number\">0</span><span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">}</span></code></pre></div>","frontmatter":{"title":"[알고리즘 정리] 최장 공통 부분 수열(LCS)","date":"April 01, 2020"}}},"pageContext":{"slug":"/Algorithm-Analysis/2020-04-01-알고리즘-최장공통부분수열(LCS)/","previous":{"fields":{"slug":"/Algorithm-Analysis/2020-03-31-알고리즘-행렬곱셈순서/"},"frontmatter":{"title":"[알고리즘 정리] 행렬 곱셈 문제 (Matrix Chain Multiplication)","category":"Algorithm-Analysis","draft":false}},"next":{"fields":{"slug":"/Operating-Systems/2020-04-01-운영체제-프로세스/"},"frontmatter":{"title":"[운영체제] 프로세스(Process)","category":"Operating-Systems","draft":false}}}},"staticQueryHashes":["2486386679","3128451518"]}