<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
  <channel>
    <title>BaaaaaaaarkingDog</title>
    <link>https://baaaaaaaaaaaaaaaaaaaaaaarkingdog.tistory.com/</link>
    <description></description>
    <language>ko</language>
    <pubDate>Tue, 21 Apr 2026 10:29:00 +0900</pubDate>
    <generator>TISTORY</generator>
    <ttl>100</ttl>
    <managingEditor>BaaaaaaaaaaaaaaaaaaaaaaarkingDog</managingEditor>
    <image>
      <title>BaaaaaaaarkingDog</title>
      <url>https://tistory1.daumcdn.net/tistory/2857156/attach/dfeaf2d0bf2d4b33bb6140dbe412e1ba</url>
      <link>https://baaaaaaaaaaaaaaaaaaaaaaarkingdog.tistory.com</link>
    </image>
    <item>
      <title>BOJ 서비스 종료에 따른 안내</title>
      <link>https://baaaaaaaaaaaaaaaaaaaaaaarkingdog.tistory.com/1108</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;백준 온라인 저지가 문을 닫는다고 합니다 &lt;a href=&quot;https://www.acmicpc.net/board/view/165799&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;(공지)&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;요즘들어 뜸하긴 했지만 그래도 10년 넘게 활동했고 특히 대학 시절의 여러 추억이 있는 곳인데 많이 아쉽네요ㅠㅠ&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 강의 또한 BOJ 플랫폼에 종속적이어서 타격을 받을 수 밖에 없습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;서비스 종료 전에 연습 문제와 문제집의 문제들을 깃헙에 마크다운으로 백업해서 열람하게 두려고는 하나, 제공되던 문제들을 아예 다른 곳으로 옮겨 채점 가능하게 두는건 당장 제가 그렇게 할 여력도 없고 설령 시간적 여유가 된다고 해도 저작권 문제로 인해 불가능합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;일단 지금 저는 박사과정 막학기라 졸업 준비로 많이 바쁜 상황입니다. 바쁜 일을 끝낸 다음에 대응 방법을 고민해보겠습니다.&lt;/p&gt;</description>
      <category>강좌/실전 알고리즘</category>
      <author>BaaaaaaaaaaaaaaaaaaaaaaarkingDog</author>
      <guid isPermaLink="true">https://baaaaaaaaaaaaaaaaaaaaaaarkingdog.tistory.com/1108</guid>
      <comments>https://baaaaaaaaaaaaaaaaaaaaaaarkingdog.tistory.com/1108#entry1108comment</comments>
      <pubDate>Sun, 19 Apr 2026 10:43:42 +0900</pubDate>
    </item>
    <item>
      <title>문제집 파이썬/자바 코드 안내</title>
      <link>https://baaaaaaaaaaaaaaaaaaaaaaarkingdog.tistory.com/1106</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://github.com/hanXen&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;대학 동기이자 개쩌는 개발자 친구&lt;/a&gt;의 도움을 받아 0x11강까지의 모든 문제에 대한 파이썬 코드를 확보했습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;또 &lt;a href=&quot;https://unluckyjung.github.io/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;아는 사람은 다 아는 실력자&lt;/a&gt;의 도움을 받아 LLM으로 C++ 정답 코드를 파이썬과 자바로 포팅하는 방식으로 남은 문제들에 대해서도 파이썬 및 자바 정답 코드를 생성하려고 합니다 (2월 안에 처리하는게 목표).&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;참고 :&amp;nbsp;&lt;a href=&quot;https://github.com/encrypted-def/basic-algo-lecture/blob/master/docs/other-languages.md&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://github.com/encrypted-def/basic-algo-lecture/blob/master/docs/other-languages.md&lt;/a&gt;&lt;/p&gt;</description>
      <category>강좌/실전 알고리즘</category>
      <author>BaaaaaaaaaaaaaaaaaaaaaaarkingDog</author>
      <guid isPermaLink="true">https://baaaaaaaaaaaaaaaaaaaaaaarkingdog.tistory.com/1106</guid>
      <comments>https://baaaaaaaaaaaaaaaaaaaaaaarkingdog.tistory.com/1106#entry1106comment</comments>
      <pubDate>Tue, 27 Jan 2026 21:23:04 +0900</pubDate>
    </item>
    <item>
      <title>30 원정대</title>
      <link>https://baaaaaaaaaaaaaaaaaaaaaaarkingdog.tistory.com/1105</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;예... 30살이 코앞입니다 20대를 떠나보내려고 하니 아주 눈물이 앞을 가립니다 시간이 왤케 빠르지&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;암튼 올해 아홉수를 보냈는데, 보통 아홉수가 무슨 삼재 어쩌구 이러면서 인생의 큰 변곡점 내지는 위기가 올 수 있으니 조심해야한다고 하는데 전 올해가 상당히 얻은게 많아서 굉장히 만족스러운 1년이었습니다.&lt;br /&gt;&lt;br /&gt;일단 2월에 예상치못하게 유로크립트 논문 accept 소식받아서 다음에 5월에 발표 잘 하고 왔고,&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;무엇보다도 6월부터는 연애를 하고있습니다. 취미나 좋아하는거 이런게 이래저래 잘 맞아서 정말 행복하게 잘 만나고 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그리고 10월에는 예전부터 꼭 30살이 되기 전에 해야겠다고 생각했던 풀코스 완주,,,!!&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1258&quot; data-origin-height=&quot;441&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dEf1B4/dJMcagjNxUx/7XjneETKo3BivNnqL15ON1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dEf1B4/dJMcagjNxUx/7XjneETKo3BivNnqL15ON1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dEf1B4/dJMcagjNxUx/7XjneETKo3BivNnqL15ON1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdEf1B4%2FdJMcagjNxUx%2F7XjneETKo3BivNnqL15ON1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1258&quot; height=&quot;441&quot; data-origin-width=&quot;1258&quot; data-origin-height=&quot;441&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;20대와 이별하는건 솔직히 좀 슬프고 언제 시간이 이렇게 됐나 싶은 마음도 있고,,ㅠ 그렇긴하지만 시간을 거스를수는 없으니 겸허히 받아들여야겠어요. 그래도 20대의 마지막을 알차게 보낼수 있어서 행복했습니다. 앞으로도 좋은일만 가득하면 좋겠네요ㅎㅎ&lt;/p&gt;</description>
      <category>일상/ETC</category>
      <author>BaaaaaaaaaaaaaaaaaaaaaaarkingDog</author>
      <guid isPermaLink="true">https://baaaaaaaaaaaaaaaaaaaaaaarkingdog.tistory.com/1105</guid>
      <comments>https://baaaaaaaaaaaaaaaaaaaaaaarkingdog.tistory.com/1105#entry1105comment</comments>
      <pubDate>Wed, 24 Dec 2025 01:03:08 +0900</pubDate>
    </item>
    <item>
      <title>마라토너(진)</title>
      <link>https://baaaaaaaaaaaaaaaaaaaaaaarkingdog.tistory.com/1104</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;요새 러닝에 꽂혀서 열심히 달리고 있습니다. 30대가 되기 전에 풀코스를 완주해보고 싶다는 생각을 예전부터 했었어서,,, 흠흠 처음 마음 먹고 러닝을 틈틈히 한건 작년 5월쯤이었는데 작년엔 소소하게 총 200km 정도 뛰었고 올해에는 춘마를 신청해서 7월부터 열심히 달리고 있습니다. 7월, 8월에 160km 뛰고 9월에는 120km 뛰었네요. 올 여름 너무 더웠는데 꾸역꾸역 거리 채우느라 진짜 정말 힘들었습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1170&quot; data-origin-height=&quot;1431&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/B318p/btsQ16Ci1DH/vxIayOSkKGnQG4PN6osNUk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/B318p/btsQ16Ci1DH/vxIayOSkKGnQG4PN6osNUk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/B318p/btsQ16Ci1DH/vxIayOSkKGnQG4PN6osNUk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FB318p%2FbtsQ16Ci1DH%2FvxIayOSkKGnQG4PN6osNUk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1170&quot; height=&quot;1431&quot; data-origin-width=&quot;1170&quot; data-origin-height=&quot;1431&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;춘마 전에 나간 하프는 1:55여서 원래는 서브4를 하고 싶었는데 약간 힘들겠다,,, 하는 생각도 좀 있네요.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;오늘 테이퍼링 전 마지막 장거리로 37km 뛰었는데 ㄹㅇ 디질뻔;; 풀코스 어떻게든 완주는 할수있을것 같은데 기록은 잘 모르겠습니다. 4:15 정도 생각해야하나... 약간 아쉽긴하지만 그래도 완주를 한다는게 중요한거니까 !!&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1080&quot; data-origin-height=&quot;1080&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/Hoi7O/btsQ2vuKAdE/32DOlBuzgLOhHji40HiOSK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/Hoi7O/btsQ2vuKAdE/32DOlBuzgLOhHji40HiOSK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/Hoi7O/btsQ2vuKAdE/32DOlBuzgLOhHji40HiOSK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FHoi7O%2FbtsQ2vuKAdE%2F32DOlBuzgLOhHji40HiOSK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1080&quot; height=&quot;1080&quot; data-origin-width=&quot;1080&quot; data-origin-height=&quot;1080&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그럼 풀코스 완주하고 돌아오겠습니다 &lt;/p&gt;</description>
      <category>일상/ETC</category>
      <author>BaaaaaaaaaaaaaaaaaaaaaaarkingDog</author>
      <guid isPermaLink="true">https://baaaaaaaaaaaaaaaaaaaaaaarkingdog.tistory.com/1104</guid>
      <comments>https://baaaaaaaaaaaaaaaaaaaaaaarkingdog.tistory.com/1104#entry1104comment</comments>
      <pubDate>Thu, 2 Oct 2025 23:09:29 +0900</pubDate>
    </item>
    <item>
      <title>현실적인 대학원생 이야기 (모교 해킹동아리 세미나 발표자료)</title>
      <link>https://baaaaaaaaaaaaaaaaaaaaaaarkingdog.tistory.com/1103</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;모교(고려대 사이버국방학과) 해킹동아리 Cykor 세미나에서 발표한 내용입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;학교에서 ctf를 활발하게 하고 있는 학생들을 대상으로 한 발표란걸 감안해서 슬라이드를 확인해주시고, 카이스트 정보보호대학원이나 아니더라도 그냥 대학원 생활에 대해 궁금한 점 있으시면 댓글로 남겨주시면 제가 아는 범위에서 답변 드리겠습니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;fileblock&quot; data-ke-align=&quot;alignCenter&quot;&gt;&lt;a href=&quot;https://blog.kakaocdn.net/dn/sTTiI/btsONdi6iWF/FOSlc3hB7Xbs4nCvc8vgJ0/%ED%98%84%EC%8B%A4%EC%A0%81%EC%9D%B8_%EB%8C%80%ED%95%99%EC%9B%90%EC%83%9D_%EC%9D%B4%EC%95%BC%EA%B8%B0.pdf?attach=1&amp;amp;knm=tfile.pdf&quot; class=&quot;&quot;&gt;
    &lt;div class=&quot;image&quot;&gt;&lt;/div&gt;
    &lt;div class=&quot;desc&quot;&gt;&lt;div class=&quot;filename&quot;&gt;&lt;span class=&quot;name&quot;&gt;현실적인_대학원생_이야기.pdf&lt;/span&gt;&lt;/div&gt;
&lt;div class=&quot;size&quot;&gt;1.27MB&lt;/div&gt;
&lt;/div&gt;
  &lt;/a&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;(슬라이드 템플릿 출처 : &lt;a href=&quot;https://yusaebyeol.blogspot.com/2020/11/powerpoint-template-free-download-ppt_22.html&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;새별의 파워포인트 PPT 템플릿&lt;/a&gt;)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;추가로 &lt;a href=&quot;https://www.slideshare.net/slideshow/ss-8add/264265176&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://www.slideshare.net/slideshow/ss-8add/264265176&lt;/a&gt; 이 슬라이드도 강추합니다.&lt;/p&gt;</description>
      <category>일상/ETC</category>
      <author>BaaaaaaaaaaaaaaaaaaaaaaarkingDog</author>
      <guid isPermaLink="true">https://baaaaaaaaaaaaaaaaaaaaaaarkingdog.tistory.com/1103</guid>
      <comments>https://baaaaaaaaaaaaaaaaaaaaaaarkingdog.tistory.com/1103#entry1103comment</comments>
      <pubDate>Mon, 23 Jun 2025 20:40:22 +0900</pubDate>
    </item>
    <item>
      <title>Eurocrypt 2025</title>
      <link>https://baaaaaaaaaaaaaaaaaaaaaaarkingdog.tistory.com/1102</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;11.jpg&quot; data-origin-width=&quot;3024&quot; data-origin-height=&quot;4032&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bIGdfp/btsNQGMnLaT/iyTfEElArnKyVg3Ph7igx1/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bIGdfp/btsNQGMnLaT/iyTfEElArnKyVg3Ph7igx1/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bIGdfp/btsNQGMnLaT/iyTfEElArnKyVg3Ph7igx1/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbIGdfp%2FbtsNQGMnLaT%2FiyTfEElArnKyVg3Ph7igx1%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;3024&quot; height=&quot;4032&quot; data-filename=&quot;11.jpg&quot; data-origin-width=&quot;3024&quot; data-origin-height=&quot;4032&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;13.jpg&quot; data-origin-width=&quot;4000&quot; data-origin-height=&quot;3000&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/b4MxvE/btsNQNSd5vY/UI9OcpkifLq19Y5mwH4GEk/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/b4MxvE/btsNQNSd5vY/UI9OcpkifLq19Y5mwH4GEk/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/b4MxvE/btsNQNSd5vY/UI9OcpkifLq19Y5mwH4GEk/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fb4MxvE%2FbtsNQNSd5vY%2FUI9OcpkifLq19Y5mwH4GEk%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;4000&quot; height=&quot;3000&quot; data-filename=&quot;13.jpg&quot; data-origin-width=&quot;4000&quot; data-origin-height=&quot;3000&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;12.jpg&quot; data-origin-width=&quot;3024&quot; data-origin-height=&quot;4032&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/czrRn6/btsNPgabKgi/gK63I4N4yt2vlNxzKgcrFk/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/czrRn6/btsNPgabKgi/gK63I4N4yt2vlNxzKgcrFk/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/czrRn6/btsNPgabKgi/gK63I4N4yt2vlNxzKgcrFk/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FczrRn6%2FbtsNPgabKgi%2FgK63I4N4yt2vlNxzKgcrFk%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;3024&quot; height=&quot;4032&quot; data-filename=&quot;12.jpg&quot; data-origin-width=&quot;3024&quot; data-origin-height=&quot;4032&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;에서 발표했습니더 어쩌다보니 이번이 연구실 외부에서 공식적으로 하는 첫 발표였는데 (아마도) 안 버벅이고 잘했습니다&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;무수한 악수의 요청 이런건 없었지만 그래도 발표 끝나고 비슷한 연구 하시는 분들이랑 얘기 나누고 그랬던,,,^^ 영어는 걱정하던것보단 괜찮았지만 그래도 약간은 버벅이는게 있어서 계속 열심히 해야겠네요 굿&lt;/p&gt;</description>
      <category>일상/ETC</category>
      <author>BaaaaaaaaaaaaaaaaaaaaaaarkingDog</author>
      <guid isPermaLink="true">https://baaaaaaaaaaaaaaaaaaaaaaarkingdog.tistory.com/1102</guid>
      <comments>https://baaaaaaaaaaaaaaaaaaaaaaarkingdog.tistory.com/1102#entry1102comment</comments>
      <pubDate>Fri, 9 May 2025 02:38:20 +0900</pubDate>
    </item>
    <item>
      <title>[실전 알고리즘] 부록 E - 다이나믹 프로그래밍 심화</title>
      <link>https://baaaaaaaaaaaaaaaaaaaaaaarkingdog.tistory.com/1101</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;figure data-ke-type=&quot;video&quot; data-ke-style=&quot;alignCenter&quot; data-video-host=&quot;youtube&quot; data-video-url=&quot;https://www.youtube.com/watch?v=cLpFW_ykJ6U&quot; data-video-thumbnail=&quot;https://scrap.kakaocdn.net/dn/4E2aU/hyYFBNWDDY/WmUpAy7rikARshXh1Of1Bk/img.jpg?width=1280&amp;amp;height=720&amp;amp;face=0_0_1280_720,https://scrap.kakaocdn.net/dn/dM6cBi/hyYIitqAI4/jGh0wiL1pugeOIZ7vO0Gi1/img.jpg?width=1280&amp;amp;height=720&amp;amp;face=0_0_1280_720&quot; data-video-width=&quot;860&quot; data-video-height=&quot;484&quot; data-video-origin-width=&quot;860&quot; data-video-origin-height=&quot;484&quot; data-ke-mobilestyle=&quot;widthContent&quot; data-video-title=&quot;[바킹독의 실전 알고리즘] 부록 E - 다이나믹 프로그래밍 심화&quot; data-original-url=&quot;&quot;&gt;&lt;iframe src=&quot;https://www.youtube.com/embed/cLpFW_ykJ6U&quot; width=&quot;860&quot; height=&quot;484&quot; frameborder=&quot;&quot; allowfullscreen=&quot;true&quot;&gt;&lt;/iframe&gt;
&lt;figcaption style=&quot;display: none;&quot;&gt;&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/rO6ig/btsNoY9cYwi/ZbMMbRRj2liHE7OREzjFPk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/rO6ig/btsNoY9cYwi/ZbMMbRRj2liHE7OREzjFPk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/rO6ig/btsNoY9cYwi/ZbMMbRRj2liHE7OREzjFPk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FrO6ig%2FbtsNoY9cYwi%2FZbMMbRRj2liHE7OREzjFPk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1920&quot; height=&quot;1080&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;268&quot; data-start=&quot;107&quot; data-ke-size=&quot;size16&quot;&gt;네, 드디어 찐막입니다. 시원섭섭하지는 않고, 굉장히 기분이 좋습니다. 마지막 피날레는 다이나믹 프로그래밍 심화로 장식하려고 합니다. 원래 본 강의에 다이나믹 프로그래밍이 포함되어 있긴 했습니다. 그런데 그 부분에서는 비교적 간단한 문제들만 다뤘기 때문에, 내용 보강이 필요하긴 했습니다.&lt;/p&gt;
&lt;p data-end=&quot;268&quot; data-start=&quot;107&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;432&quot; data-start=&quot;270&quot; data-ke-size=&quot;size16&quot;&gt;코딩 테스트를 기준으로 하더라도 0x10강에서 다룬 수준보다는 더 어려운 문제가 충분히 출제될 수 있습니다. 그렇다고 해서 다이나믹 프로그래밍을 처음 접한 상황에서 어려운 문제들까지 모두 다루기는 어렵습니다. 그래서 문제집에 문제들만 많이 모아두고, 알아서 풀면서 익혀보라는 방식이었습니다.&lt;/p&gt;
&lt;p data-end=&quot;432&quot; data-start=&quot;270&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;592&quot; data-start=&quot;434&quot; data-ke-size=&quot;size16&quot;&gt;저는 다이나믹 프로그래밍만큼은 강의에서 엄청 특별한 팁을 드리기 어렵다고 생각합니다. 결국 문제를 보고 테이블을 어떻게 잡고, 식을 어떻게 세울지를 스스로 알아내야 합니다. 이 부분은 특별한 테크닉이 필요한 것이 아니라, 많은 DP 문제를 접하면서 그 감각을 익히는 수밖에 없습니다.&lt;/p&gt;
&lt;p data-end=&quot;592&quot; data-start=&quot;434&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;780&quot; data-start=&quot;594&quot; data-ke-size=&quot;size16&quot;&gt;그래서 0x10강에서 같이 풀었던 문제들 외에도, 문제집에 있는 문제들을 가지고 고민을 많이 해보시고, 풀이도 찾아보셨다면 자연스럽게 실력이 향상되었을 것입니다. 그럼에도 불구하고 이번에 다이나믹 프로그래밍 심화 단원을 새로 만든 이유는, 자주 등장하는 DP 유형을 다시 한번 정리하고, 좋은 문제들을 추천해드리고 싶었기 때문입니다. 그러면 강의를 시작하겠습니다.&lt;/p&gt;
&lt;p data-end=&quot;780&quot; data-start=&quot;594&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/liuwG/btsNroAaojd/6K9XQa8CA0FcpbSkg7GqLK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/liuwG/btsNroAaojd/6K9XQa8CA0FcpbSkg7GqLK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/liuwG/btsNroAaojd/6K9XQa8CA0FcpbSkg7GqLK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FliuwG%2FbtsNroAaojd%2F6K9XQa8CA0FcpbSkg7GqLK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1920&quot; height=&quot;1080&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;252&quot; data-start=&quot;79&quot; data-ke-size=&quot;size16&quot;&gt;우선 다이나믹 프로그래밍(DP)이 무엇인지에 대해 조금 더 심화된 내용까지 포함하여 다시 한 번 짚어보겠습니다. 그리고 2차원 DP 문제도 몇 가지 함께 풀어볼 예정입니다. 다음으로는 기존 DP 단원에서는 설명드리지 못했던 Top-down 방식으로 DP를 해결하는 방법에 대해서도 설명드릴 예정입니다. 마지막으로 트리 DP와 위상 정렬을 활용한 DP 문제도 함께 풀어보면 이번 단원이 마무리됩니다. 이번 단원에서도 다양한 문제를 많이 풀어볼 예정이며, 문제집에도 문제를 충분히 수록해둘 예정이니, 열심히 풀어보시기 바랍니다.&lt;/p&gt;
&lt;p data-end=&quot;252&quot; data-start=&quot;79&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;슬라이드3.PNG&quot; data-origin-width=&quot;2000&quot; data-origin-height=&quot;1125&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/opeSP/btsNsaODtAk/4E14ezFv1A9vSoNm2DCRp0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/opeSP/btsNsaODtAk/4E14ezFv1A9vSoNm2DCRp0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/opeSP/btsNsaODtAk/4E14ezFv1A9vSoNm2DCRp0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FopeSP%2FbtsNsaODtAk%2F4E14ezFv1A9vSoNm2DCRp0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;2000&quot; height=&quot;1125&quot; data-filename=&quot;슬라이드3.PNG&quot; data-origin-width=&quot;2000&quot; data-origin-height=&quot;1125&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;243&quot; data-start=&quot;74&quot; data-ke-size=&quot;size16&quot;&gt;원래 다이나믹 프로그래밍(DP) 단원에서 알고리즘을 소개할 때 사용했던 슬라이드를 다시 가져왔습니다. 이 슬라이드가 무엇을 의미하는지는 기억하시죠? 피보나치 수열을 계산할 때, 중간값을 저장하지 않고 단순히 재귀 호출만 반복하면 중복 계산이 계속 발생하게 되어, 시간 복잡도가 지수적으로 증가합니다. 반면, 배열을 미리 선언하고 중간 결과를 저장하는 방식으로 DP를 적용하면, 의도한 대로 &lt;span&gt;&lt;span&gt;N&lt;/span&gt;&lt;/span&gt;번째 피보나치 수를 &lt;span&gt;&lt;span&gt;O(N)&lt;/span&gt;&lt;/span&gt;&amp;nbsp;시간에 계산할 수 있습니다.&lt;/p&gt;
&lt;p data-end=&quot;537&quot; data-start=&quot;343&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;537&quot; data-start=&quot;343&quot; data-ke-size=&quot;size16&quot;&gt;처음 강의를 구성하면서 DP를 소개드릴 때에는 &quot;그렇게 어렵지 않다&quot;, &quot;구현이 비교적 간단한 편이다&quot;라고 설명드렸습니다. 실제로 저 자신도 DP가 크게 어렵지는 않을 것이라고 생각했었습니다. 그러나 막상 강의를 만들고 나서, 수강하신 많은 분들로부터 &quot;DP가 정말 어렵다&quot;는 후기를 받으면서, 제가 예상했던 것과는 많이 다르다는 점을 느꼈습니다.&lt;/p&gt;
&lt;p data-end=&quot;707&quot; data-start=&quot;539&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;707&quot; data-start=&quot;539&quot; data-ke-size=&quot;size16&quot;&gt;하지만 한 가지 말씀드릴 수 있는 점은, 적어도 코딩 테스트 수준에서는 오히려 DP가 다른 알고리즘보다 유리할 수도 있다는 점입니다. 예를 들어 그리디나 구현 유형의 문제는 출제자의 의도나 문제 구성 방식에 따라 완전히 새로운 형태로 등장할 수 있기 때문에, 유사한 문제를 찾기가 어렵습니다. 반면 DP 문제는 출제자가 난이도를 비정상적으로 높이지 않는 한, 반드시 일정한 방식으로 테이블을 잡고 점화식을 세우는 패턴이 존재합니다. 그렇기 때문에 제가 계속 강조드리는 부분이기도 하지만, 좋은 문제들을 많이 풀어보면서 다양한 유형을 익히면 충분히 대비할 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;슬라이드4.PNG&quot; data-origin-width=&quot;2000&quot; data-origin-height=&quot;1125&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bfycKp/btsNrznRGha/CvjjwAM5yr4tzXkLenNSH0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bfycKp/btsNrznRGha/CvjjwAM5yr4tzXkLenNSH0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bfycKp/btsNrznRGha/CvjjwAM5yr4tzXkLenNSH0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbfycKp%2FbtsNrznRGha%2FCvjjwAM5yr4tzXkLenNSH0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;2000&quot; height=&quot;1125&quot; data-filename=&quot;슬라이드4.PNG&quot; data-origin-width=&quot;2000&quot; data-origin-height=&quot;1125&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;168&quot; data-start=&quot;78&quot; data-ke-size=&quot;size16&quot;&gt;그리고 처음 다이나믹 프로그래밍을 다뤘을 때와는 달리 지금은 그래프에 대한 내용을 학습한 이후이기 때문에 DP에 대해 좀 더 깊이 있는 설명을 드릴 수 있습니다. 지금 왼쪽에 있는 코드는 피보나치 수열을 DP로 구하는 예제입니다. 그렇다면 오른쪽에 있는 그래프는 무엇을 의미할까요? 아마 금방 눈치채실 수 있을 것 같지만 예를 들어 0과 1에서 화살표가 출발해서 2로 이어지고 있는데, 이 화살표가 뜻하는 것은 출발한 위치의 값이 먼저 계산되어야 도착한 위치의 값을 계산할 수 있다는 의미입니다. 이렇게 되면 자연스럽게 이런 선후 관계를 만족하는 순서로 테이블을 채워야 합니다. 예를 들어 f[0], f[1], f[2]와 같은 순서로 값을 채우면 f[i]를 계산하기 위해 필요한 f[i-1], f[i-2]가 이미 계산되어 있기 때문에 문제가 없습니다. 반대로 f[5], f[4], ..., f[0] 순서로 채우려고 하면 필요한 값이 아직 계산되지 않은 경우가 생기기 때문에 문제가 생깁니다.&lt;/p&gt;
&lt;p data-end=&quot;687&quot; data-start=&quot;600&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;687&quot; data-start=&quot;600&quot; data-ke-size=&quot;size16&quot;&gt;여기서 방향 그래프와 선후 관계라는 말이 나왔으니 자연스럽게 떠오르는 개념이 있을 겁니다. 바로 위상 정렬입니다. 이전에 위상 정렬 단원에서 배운 내용입니다. 결국 DP에서 테이블을 채운다는 것은 채워야 할 각 칸을 정점으로 보고 그 칸들 사이의 선후 관계를 그래프로 나타냈을 때 위상 정렬 순서에 따라 값을 채워야 한다는 뜻입니다. 쉬운 문제에서는 보통 0부터 차례로 채우는 방식처럼 이 흐름이 직관적으로 드러나기 때문에 이전에는 이렇게까지 깊게 설명드리지는 않았지만 오늘 배울 내용을 이해하는 데에는 지금 말씀드린 이 개념을 알고 있는 것이 도움이 됩니다.&lt;/p&gt;
&lt;p data-end=&quot;687&quot; data-start=&quot;600&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;슬라이드5.PNG&quot; data-origin-width=&quot;2000&quot; data-origin-height=&quot;1125&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/zX4Ap/btsNslWGIDL/XNUGM0d67RszRwMiqaSkmk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/zX4Ap/btsNslWGIDL/XNUGM0d67RszRwMiqaSkmk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/zX4Ap/btsNslWGIDL/XNUGM0d67RszRwMiqaSkmk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FzX4Ap%2FbtsNslWGIDL%2FXNUGM0d67RszRwMiqaSkmk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;2000&quot; height=&quot;1125&quot; data-filename=&quot;슬라이드5.PNG&quot; data-origin-width=&quot;2000&quot; data-origin-height=&quot;1125&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;265&quot; data-start=&quot;89&quot; data-ke-size=&quot;size16&quot;&gt;또 하나 흥미로운 점은 DP의 상황을 그래프로 나타냈을 때 사이클이 생기면 어떻게 될까 하는 부분입니다. 예를 들어 f[0]을 채우기 위해 f[2]가 필요하고 f[2]를 채우기 위해 f[1]이 필요하며 f[1]을 채우기 위해 다시 f[0]이 필요하다면 서로 물고 물리게 되어 어떤 값도 먼저 계산할 수 없게 됩니다.&lt;/p&gt;
&lt;p data-end=&quot;265&quot; data-start=&quot;89&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;442&quot; data-start=&quot;267&quot; data-ke-size=&quot;size16&quot;&gt;이처럼 셋 중 무엇도 먼저 구할 수 없는 상황이 되면 DP 풀이가 불가능해집니다. 그래서 DP의 테이블을 정의하고 점화식을 세운 뒤 그 구조를 그래프로 표현한다고 했을 때에는 사이클이 존재하면 안 됩니다. 다시 말해 방향 그래프이면서 사이클이 없는 DAG, 즉 Directed Acyclic Graph여야 합니다. 그리고 이 DAG 구조를 기반으로 위상 정렬 순서에 따라 테이블을 채워나가게 되는데 이때 진입 차수, 즉 indegree가 0인 정점들은 초기값이 됩니다. 앞서 본 피보나치 수열의 경우에서 f[0]과 f[1]이 초기값이었던 것과 같은 원리입니다.&lt;/p&gt;
&lt;p data-end=&quot;442&quot; data-start=&quot;267&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;슬라이드6.PNG&quot; data-origin-width=&quot;2000&quot; data-origin-height=&quot;1125&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bER72d/btsNr9ITz8Y/RUhF9B3WwOdCKJVgSRCLO0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bER72d/btsNr9ITz8Y/RUhF9B3WwOdCKJVgSRCLO0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bER72d/btsNr9ITz8Y/RUhF9B3WwOdCKJVgSRCLO0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbER72d%2FbtsNr9ITz8Y%2FRUhF9B3WwOdCKJVgSRCLO0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;2000&quot; height=&quot;1125&quot; data-filename=&quot;슬라이드6.PNG&quot; data-origin-width=&quot;2000&quot; data-origin-height=&quot;1125&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;209&quot; data-start=&quot;76&quot; data-ke-size=&quot;size16&quot;&gt;네, 그러면 일단 앞 챕터에서 다뤘던 내용은 잠시 접어두고 2차원 DP 문제들부터 차례로 풀어보겠습니다. 총 네 개의 문제를 함께 볼 예정인데&amp;nbsp;비록 원래 DP 강의 안에서 같이 다루지는 못했지만 DP의 전형적인 구조를 잘 보여주는 좋은 문제들이기 때문에 만약 이전에 풀어보신 적이 있다면 복습 차원에서 다시 한번 생각해보시고 처음 보는 문제라면 DP가 늘 그렇듯 테이블을 어떻게 정의하고 점화식을 어떻게 세우는지를 중심으로 살펴보면 좋습니다.&lt;/p&gt;
&lt;p data-end=&quot;490&quot; data-start=&quot;375&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;490&quot; data-start=&quot;375&quot; data-ke-size=&quot;size16&quot;&gt;먼저 볼 문제는 &lt;a href=&quot;https://www.acmicpc.net/problem/9251&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;BOJ 9251번: LCS&lt;/a&gt; 문제입니다. 여기서 테이블을 잘 정의하고 점화식을 찾은 뒤 초기값을 설정하는 것이 이 문제를 DP로 해결하기 위해 우리가 해야 할 일입니다.&lt;/p&gt;
&lt;p data-end=&quot;490&quot; data-start=&quot;375&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;슬라이드7.PNG&quot; data-origin-width=&quot;2000&quot; data-origin-height=&quot;1125&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bfzUGm/btsNsl3pkH6/YLZvGIa21W8ebRItc5WSxk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bfzUGm/btsNsl3pkH6/YLZvGIa21W8ebRItc5WSxk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bfzUGm/btsNsl3pkH6/YLZvGIa21W8ebRItc5WSxk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbfzUGm%2FbtsNsl3pkH6%2FYLZvGIa21W8ebRItc5WSxk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;2000&quot; height=&quot;1125&quot; data-filename=&quot;슬라이드7.PNG&quot; data-origin-width=&quot;2000&quot; data-origin-height=&quot;1125&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;252&quot; data-start=&quot;91&quot; data-ke-size=&quot;size16&quot;&gt;이제 테이블을 정의해야 하는데, 이번 단원이 2차원 DP이기 때문에 직관적으로 떠오르는 형태로 테이블을 먼저 정해보겠습니다. 이렇게 앞의 몇 개 값을 기준으로 테이블을 구성하는 방식은 이전에도 여러 번 사용했던 구조입니다. 물론 지금은 2차원이긴 하지만, 충분히 시도해볼 만한 형태입니다.&lt;/p&gt;
&lt;p data-end=&quot;362&quot; data-start=&quot;254&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;362&quot; data-start=&quot;254&quot; data-ke-size=&quot;size16&quot;&gt;이제 이 테이블을 기반으로 점화식을 만들 수 있는지를 확인해야 합니다. 점화식을 만든다는 것은 지금 D[i][j]를 구할 때 이전에 계산된 값을 어떻게 활용할 수 있을지를 생각해보는 과정입니다. 이를 위해 첫 번째 문자열의 앞 i글자와 두 번째 문자열의 앞 j글자에서 LCS가 어떤 식으로 나올 수 있을지를 케이스별로 나누어 살펴보겠습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;슬라이드8.PNG&quot; data-origin-width=&quot;2000&quot; data-origin-height=&quot;1125&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/k7E74/btsNtdDmHt0/ms0lzWdb1GePEEGOzaBnKk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/k7E74/btsNtdDmHt0/ms0lzWdb1GePEEGOzaBnKk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/k7E74/btsNtdDmHt0/ms0lzWdb1GePEEGOzaBnKk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fk7E74%2FbtsNtdDmHt0%2Fms0lzWdb1GePEEGOzaBnKk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;2000&quot; height=&quot;1125&quot; data-filename=&quot;슬라이드8.PNG&quot; data-origin-width=&quot;2000&quot; data-origin-height=&quot;1125&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;197&quot; data-start=&quot;61&quot; data-ke-size=&quot;size16&quot;&gt;케이스를 어떻게 나눌 수 있을지에 대해서는 LCS에서 마지막으로 일치하는 글자를 기준으로 생각해보면 됩니다. 예를 들어 문제에 주어진 예시인 ACAYKP와 CAPCAK의 경우 둘의 LCS는 ACAK이고, 마지막으로 일치하는 글자는 K입니다. 이제 이 글자가 각각의 문자열에서 어디에 위치해 있는지를 기준으로 생각해보겠습니다.&lt;/p&gt;
&lt;p data-end=&quot;197&quot; data-start=&quot;61&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;슬라이드9.PNG&quot; data-origin-width=&quot;2000&quot; data-origin-height=&quot;1125&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cicObq/btsNteI2GeM/vJHSMgbsjZOYZ6igblI1nK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cicObq/btsNteI2GeM/vJHSMgbsjZOYZ6igblI1nK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cicObq/btsNteI2GeM/vJHSMgbsjZOYZ6igblI1nK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcicObq%2FbtsNteI2GeM%2FvJHSMgbsjZOYZ6igblI1nK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;2000&quot; height=&quot;1125&quot; data-filename=&quot;슬라이드9.PNG&quot; data-origin-width=&quot;2000&quot; data-origin-height=&quot;1125&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;200&quot; data-start=&quot;101&quot; data-ke-size=&quot;size16&quot;&gt;먼저 따져볼 수 있는 케이스는 두 문자열의 마지막 글자가 일치하는 경우입니다. 이 경우에는 이전의 테이블 값을 활용해서 D[i][j]를 계산할 수 있겠다는 느낌이 바로 옵니다. 마지막 글자를 떼어내고 나머지 부분에서 LCS를 구한 뒤, 그 결과에 마지막 글자를 하나 더해주면 되기 때문입니다. 여기서 말하는 나머지 부분은 첫 번째 문자열의 앞 i-1글자와 두 번째 문자열의 앞 j-1글자를 의미하므로, D[i-1][j-1]을 참조하면 됩니다. 따라서 이 경우에는 D[i][j]는 D[i-1][j-1]에 1을 더한 값이 됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;슬라이드10.PNG&quot; data-origin-width=&quot;2000&quot; data-origin-height=&quot;1125&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/ebC0NT/btsNsiFEOqU/pSc6PX10jcO8H1TGeJkgA0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/ebC0NT/btsNsiFEOqU/pSc6PX10jcO8H1TGeJkgA0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/ebC0NT/btsNsiFEOqU/pSc6PX10jcO8H1TGeJkgA0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FebC0NT%2FbtsNsiFEOqU%2FpSc6PX10jcO8H1TGeJkgA0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;2000&quot; height=&quot;1125&quot; data-filename=&quot;슬라이드10.PNG&quot; data-origin-width=&quot;2000&quot; data-origin-height=&quot;1125&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;155&quot; data-start=&quot;56&quot; data-ke-size=&quot;size16&quot;&gt;그리고 두 번째 케이스는 첫 번째 문자열의 마지막 글자가 LCS에 포함되지 않는 경우입니다. 이때 두 번째 문자열의 마지막 글자는 LCS에 포함될 수도 있고 아닐 수도 있습니다. 이런 상황에서는 일치하는 다른 글자를 찾아야 하는 걸까 하는 생각이 들 수 있지만, 훨씬 더 간단하게 접근할 수 있는 방법이 있습니다. 이미 첫 번째 문자열의 마지막 글자가 LCS에 들어가지 않는다고 가정했기 때문에, 이 글자는 LCS를 구성하는 데 아무런 기여를 하지 못합니다. 그렇다면 그냥 이 글자를 제외한 나머지 부분들로만 LCS를 찾으면 됩니다. 즉, 첫 번째 문자열에서 마지막 글자를 뺀 부분과 두 번째 문자열 전체로 구한 LCS가 이 경우의 결과가 되며, 이는 D[i-1][j]로 나타낼 수 있습니다.&lt;/p&gt;
&lt;p data-end=&quot;507&quot; data-start=&quot;447&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;507&quot; data-start=&quot;447&quot; data-ke-size=&quot;size16&quot;&gt;이제 이 과정을 따라오면서 LCS 문제가 어떻게 DP로 풀리는지 어느 정도 감이 잡히셨을 거라고 생각합니다.&lt;/p&gt;
&lt;p data-end=&quot;507&quot; data-start=&quot;447&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;슬라이드11.PNG&quot; data-origin-width=&quot;2000&quot; data-origin-height=&quot;1125&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bh1Spb/btsNsPwbS1H/tfr0PPs7eKawA6fiNo0ngK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bh1Spb/btsNsPwbS1H/tfr0PPs7eKawA6fiNo0ngK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bh1Spb/btsNsPwbS1H/tfr0PPs7eKawA6fiNo0ngK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fbh1Spb%2FbtsNsPwbS1H%2Ftfr0PPs7eKawA6fiNo0ngK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;2000&quot; height=&quot;1125&quot; data-filename=&quot;슬라이드11.PNG&quot; data-origin-width=&quot;2000&quot; data-origin-height=&quot;1125&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그리고 마지막 케이스는 두 번째 문자열의 마지막 글자가 LCS에 포함되지 않는 경우입니다. 이 경우에는 앞서 설명한 흐름과 마찬가지로 해당 글자가 LCS에 기여하지 않기 때문에, 나머지 부분으로만 LCS를 구하면 됩니다. 따라서 이 경우에는 D[i][j-1]이 결과가 됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;슬라이드12.PNG&quot; data-origin-width=&quot;2000&quot; data-origin-height=&quot;1125&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/7D6LE/btsNo1rma4S/aa0BKRU0uO4YYRTXLkwTA1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/7D6LE/btsNo1rma4S/aa0BKRU0uO4YYRTXLkwTA1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/7D6LE/btsNo1rma4S/aa0BKRU0uO4YYRTXLkwTA1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F7D6LE%2FbtsNo1rma4S%2Faa0BKRU0uO4YYRTXLkwTA1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;2000&quot; height=&quot;1125&quot; data-filename=&quot;슬라이드12.PNG&quot; data-origin-width=&quot;2000&quot; data-origin-height=&quot;1125&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;166&quot; data-start=&quot;78&quot; data-ke-size=&quot;size16&quot;&gt;D[i][j]에서의 LCS를 생각해보면, 두 문자열의 마지막 글자가 모두 포함되는 경우이거나, 아니면 적어도 하나는 포함되지 않는 경우일 수밖에 없습니다.&lt;/p&gt;
&lt;p data-end=&quot;166&quot; data-start=&quot;78&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;312&quot; data-start=&quot;170&quot; data-ke-size=&quot;size16&quot;&gt;따라서 이 세 가지 경우를 나누어 보면 모든 상황을 다 처리할 수 있게 됩니다. 그리고 첫 번째 케이스는 두 문자열의 마지막 글자가 같은 경우에만 고려하면 되므로, 최종적으로 D[i][j]는 각 경우의 값 중에서 최댓값을 취하는 방식으로 계산하면 됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;슬라이드13.PNG&quot; data-origin-width=&quot;2000&quot; data-origin-height=&quot;1125&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/MHGgp/btsNsTd3yOj/oQQAzFOtkonZ3ukEkGIwk0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/MHGgp/btsNsTd3yOj/oQQAzFOtkonZ3ukEkGIwk0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/MHGgp/btsNsTd3yOj/oQQAzFOtkonZ3ukEkGIwk0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FMHGgp%2FbtsNsTd3yOj%2FoQQAzFOtkonZ3ukEkGIwk0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;2000&quot; height=&quot;1125&quot; data-filename=&quot;슬라이드13.PNG&quot; data-origin-width=&quot;2000&quot; data-origin-height=&quot;1125&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;133&quot; data-start=&quot;72&quot; data-ke-size=&quot;size16&quot;&gt;테이블을 잘 정의하고 점화식도 잡아냈으니, 이제 초기값을 설정하고 테이블을 채우는 순서만 생각하면 됩니다. 일단 초기값은 D[0][...]과 D[...][0]의 값을 0으로 두는 것이 구현을 깔끔하고 편하게 해줍니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;슬라이드14.PNG&quot; data-origin-width=&quot;2000&quot; data-origin-height=&quot;1125&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/beYBpU/btsNsiySgey/M1A4zYIcKonWBXvfw8LEPK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/beYBpU/btsNsiySgey/M1A4zYIcKonWBXvfw8LEPK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/beYBpU/btsNsiySgey/M1A4zYIcKonWBXvfw8LEPK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbeYBpU%2FbtsNsiySgey%2FM1A4zYIcKonWBXvfw8LEPK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;2000&quot; height=&quot;1125&quot; data-filename=&quot;슬라이드14.PNG&quot; data-origin-width=&quot;2000&quot; data-origin-height=&quot;1125&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그리고 값을 채우는 순서는 1차원 배열에서 자기보다 작은 인덱스만 참고해서 D[0], D[1], D[2], ... 순으로 채우는 것과 비슷하게 생각할 수 있습니다. 지금도 D[i][j]의 값을 구할 때 D[i-1][j-1], D[i-1][j], D[i][j-1]를 참고하므로, 테이블을 보면 필요한 값들은 모두 나보다 왼쪽 혹은 위쪽에 위치한 값들만 필요하다는 것을 알 수 있습니다. 예를 들어 D[4][4]를 구한다고 할 때, 필요한 칸인 D[3][3], D[3][4], D[4][3]은 모두 왼쪽이나 위쪽에 위치한 값들입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;슬라이드15.PNG&quot; data-origin-width=&quot;2000&quot; data-origin-height=&quot;1125&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dZRidE/btsNsbNynRR/Xv7PdLqEiuj4QTbt6ehrg1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dZRidE/btsNsbNynRR/Xv7PdLqEiuj4QTbt6ehrg1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dZRidE/btsNsbNynRR/Xv7PdLqEiuj4QTbt6ehrg1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdZRidE%2FbtsNsbNynRR%2FXv7PdLqEiuj4QTbt6ehrg1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;2000&quot; height=&quot;1125&quot; data-filename=&quot;슬라이드15.PNG&quot; data-origin-width=&quot;2000&quot; data-origin-height=&quot;1125&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;234&quot; data-start=&quot;55&quot; data-ke-size=&quot;size16&quot;&gt;그러면 그냥 이렇게 D[1][1], D[1][2], D[1][3], D[1][4], D[2][1], ..., D[4][4] 순으로 채우면 자연스럽게 각 칸의 값을 구할 때 자신의 왼쪽 혹은 윗쪽에 있는 모든 칸이 채워져 있기 때문에 아무 문제 없이 답을 구할 수 있습니다. 이제 이것들을 종합해서 구현을 한 번 해보세요.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;슬라이드16.PNG&quot; data-origin-width=&quot;2000&quot; data-origin-height=&quot;1125&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/05aHE/btsNsUKPG7b/Ok3NudnBhdtnlurk9UmIM0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/05aHE/btsNsUKPG7b/Ok3NudnBhdtnlurk9UmIM0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/05aHE/btsNsUKPG7b/Ok3NudnBhdtnlurk9UmIM0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F05aHE%2FbtsNsUKPG7b%2FOk3NudnBhdtnlurk9UmIM0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;2000&quot; height=&quot;1125&quot; data-filename=&quot;슬라이드16.PNG&quot; data-origin-width=&quot;2000&quot; data-origin-height=&quot;1125&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;165&quot; data-start=&quot;64&quot; data-ke-size=&quot;size16&quot;&gt;네, 구현은 크게 특이사항이 없습니다. 처음에 초기값을 D[0][...]과 D[...][0]에 넣어줘야 하지만 사실 D를 전역 변수로 잡으면 알아서 0이 들어갈 테니 괜찮습니다. 그리고 이 문제가 절대 쉬운 문제가 아닙니다. 보통 점화식이 수학적으로 비교적 당연하게 구해지면 문제가 쉽다고 생각할 수 있는데, LCS에서는 D[i][j]의 답의 형태에 따라 케이스를 나누어서 점화식을 이끌어내야 했기 때문에 정말 어려운 문제입니다. 이 문제는 DP를 배울 때 보통 꼭 짚고 가게 되는 유명한 문제여서 소개를 드리긴 했지만, 혹시 좀 헷갈리거나 너무 고통을 받으셨다면 어려운 게 당연하다는 걸로 위안을 삼으시길 바랍니다. 또 한편으로는 이 문제에서 점화식을 이끌어냈던 논리 전개 과정은 꼭 숙지하시기를 추천드립니다. &lt;a href=&quot;https://github.com/encrypted-def/basic-algo-lecture/blob/master/Appendix%20E/9251.cpp&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;(코드)&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;슬라이드17.PNG&quot; data-origin-width=&quot;2000&quot; data-origin-height=&quot;1125&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cjVqsB/btsNreiRnio/OBLiJK69cfKqlD1L7qA10k/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cjVqsB/btsNreiRnio/OBLiJK69cfKqlD1L7qA10k/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cjVqsB/btsNreiRnio/OBLiJK69cfKqlD1L7qA10k/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcjVqsB%2FbtsNreiRnio%2FOBLiJK69cfKqlD1L7qA10k%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;2000&quot; height=&quot;1125&quot; data-filename=&quot;슬라이드17.PNG&quot; data-origin-width=&quot;2000&quot; data-origin-height=&quot;1125&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;164&quot; data-start=&quot;41&quot; data-ke-size=&quot;size16&quot;&gt;두 번째로 같이 풀어볼 문제는 &lt;a href=&quot;https://www.acmicpc.net/problem/9084&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;BOJ 9084번: 동전&lt;/a&gt; 문제입니다. 사실 저희가 &lt;a href=&quot;https://www.acmicpc.net/problem/11047&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;비슷한 문제&lt;/a&gt;를 풀어본 적이 있는데, 10원, 50원, 100원, 500원 이런 식으로 배수 관계가 성립할 때에는 그리디 알고리즘으로 쉽게 풀이가 가능합니다.&lt;/p&gt;
&lt;p data-end=&quot;164&quot; data-start=&quot;41&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;344&quot; data-start=&quot;168&quot; data-ke-size=&quot;size16&quot;&gt;하지만 지금 문제처럼 동전들 사이에 배수 관계가 없다는 조건이 주어지면, 그리디 알고리즘으로는 해결할 수 없습니다. 한편, 지금 문제처럼 총 경우의 수를 구해야 하고, 심지어 그 경우의 수가 거의 2^31 &amp;ndash; 1에 가까운 만큼 많아서 백트래킹 같은 방법으로 해결이 어려울 경우, DP로 풀 수 있는 경우가 많습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;슬라이드18.PNG&quot; data-origin-width=&quot;2000&quot; data-origin-height=&quot;1125&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/beYLkn/btsNsUxgYVF/guGYFmXVlr94l8AbC8Js21/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/beYLkn/btsNsUxgYVF/guGYFmXVlr94l8AbC8Js21/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/beYLkn/btsNsUxgYVF/guGYFmXVlr94l8AbC8Js21/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbeYLkn%2FbtsNsUxgYVF%2FguGYFmXVlr94l8AbC8Js21%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;2000&quot; height=&quot;1125&quot; data-filename=&quot;슬라이드18.PNG&quot; data-origin-width=&quot;2000&quot; data-origin-height=&quot;1125&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;일단 테이블을 먼저 정의해보면, D[i]를 i원을 만드는 방법의 수로 두어 보겠습니다. 그런 다음 점화식을 구해야 하는데, 제일 마지막에 더하는 수를 가지고 점화식을 세울 수 있겠다는 느낌이 오시나요? 사실 원래 DP 단원에서 비슷한 문제를 같이 풀어봤습니다. &lt;a href=&quot;https://www.acmicpc.net/problem/9095&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;BOJ 9095번: 1, 2, 3 더하기&lt;/a&gt; 문제를 확인해 보세요.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;슬라이드19.PNG&quot; data-origin-width=&quot;2000&quot; data-origin-height=&quot;1125&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/8KX7G/btsNsGsbb0m/n1c50toJuKy5XVoVanucH0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/8KX7G/btsNsGsbb0m/n1c50toJuKy5XVoVanucH0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/8KX7G/btsNsGsbb0m/n1c50toJuKy5XVoVanucH0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F8KX7G%2FbtsNsGsbb0m%2Fn1c50toJuKy5XVoVanucH0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;2000&quot; height=&quot;1125&quot; data-filename=&quot;슬라이드19.PNG&quot; data-origin-width=&quot;2000&quot; data-origin-height=&quot;1125&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;272&quot; data-start=&quot;39&quot; data-ke-size=&quot;size16&quot;&gt;9095번 문제의 느낌을 살려서 점화식을 구해본다면, N가지 동전의 가치가 c[1], c[2], ..., c[N]이라고 할 때 마지막에 추가되는 동전이 c[1]인지, c[2]인지, ..., c[N]인지를 가지고 지금 적힌 식과 같은 형태를 떠올릴 수 있습니다. 예를 들어 마지막에 추가되는 동전이 c[1]이라면 D[i-c[1]]로 i-c[1]원을 만들고 거기에 c[1] 동전을 더하는 방식으로 생각할 수 있습니다.&lt;/p&gt;
&lt;p data-end=&quot;272&quot; data-start=&quot;39&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;603&quot; data-start=&quot;274&quot; data-ke-size=&quot;size16&quot;&gt;그리고 초기값을 바로 이어서 생각해 보면, 초기값을 어떻게 정해야 할지 막연할 수 있는데 이 문제에서는 D[0], 즉 0원을 만드는 경우의 수가 1개라고 정하는 것이 가장 깔끔합니다. 이 부분은 마치 2^0이 왜 1인 것과 비슷하게 직관적으로 잘 받아들여지지 않을 수 있습니다. 그러나 이런 방식으로 생각할 수 있습니다. j번째 동전 1개만을 써서 c[j]원을 만드는 경우가 D[c[j]]에 추가되어야 합니다. 이 경우는 i = D[c[j]]일 때 점화식에서 D[i-c[j]]에서 처리가 될 텐데, 이 값이 경우의 수 1가지로 D[i]에 더해지려면 D[0] = 1인 것이 자연스럽습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;슬라이드20.PNG&quot; data-origin-width=&quot;2000&quot; data-origin-height=&quot;1125&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cfGnwX/btsNsbGKmul/OO10IUTEOzTkYeqrz65ZZ1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cfGnwX/btsNsbGKmul/OO10IUTEOzTkYeqrz65ZZ1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cfGnwX/btsNsbGKmul/OO10IUTEOzTkYeqrz65ZZ1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcfGnwX%2FbtsNsbGKmul%2FOO10IUTEOzTkYeqrz65ZZ1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;2000&quot; height=&quot;1125&quot; data-filename=&quot;슬라이드20.PNG&quot; data-origin-width=&quot;2000&quot; data-origin-height=&quot;1125&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그러면 이제 바로 코딩에 들어가면 되는 것 아닌가? 라는 생각을 하기 전에, 작은 테스트 케이스를 직접 한번 계산해보겠습니다. N = 2이고 동전이 1원, 2원일 때 D[3]까지 구해보면, 여기 적힌 것과 같이 계산되고 D[3] = 3이 나옵니다. 그런데 사실 3원을 만드는 방법은 1원짜리 3개 혹은 1원 1개와 2원 1개를 쓰는 방법 이 2가지밖에 없습니다. 어? 뭔가 좀 이상한 점이 있죠? 분명 D[3]은 2여야 할 텐데, 이게 어디서부터 잘못된 걸까요?&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;슬라이드21.PNG&quot; data-origin-width=&quot;2000&quot; data-origin-height=&quot;1125&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bC1tID/btsNsm14m91/9JfFnkbiU4W7U5Y1SaGYwk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bC1tID/btsNsm14m91/9JfFnkbiU4W7U5Y1SaGYwk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bC1tID/btsNsm14m91/9JfFnkbiU4W7U5Y1SaGYwk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbC1tID%2FbtsNsm14m91%2F9JfFnkbiU4W7U5Y1SaGYwk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;2000&quot; height=&quot;1125&quot; data-filename=&quot;슬라이드21.PNG&quot; data-origin-width=&quot;2000&quot; data-origin-height=&quot;1125&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;142&quot; data-start=&quot;40&quot; data-ke-size=&quot;size16&quot;&gt;각 D[i] 값이 어떤 경우들을 포함하는지를 따져보면, 무엇이 잘못되었는지가 쉽게 보입니다. 일단 D[1]부터 살펴보면, D[0]부터 온 값은 1원짜리 동전을 1개 쓰는 경우입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;슬라이드22.PNG&quot; data-origin-width=&quot;2000&quot; data-origin-height=&quot;1125&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/rdjML/btsNrcyDIyD/C8k9jeTBjivlURlS2iRVS0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/rdjML/btsNrcyDIyD/C8k9jeTBjivlURlS2iRVS0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/rdjML/btsNrcyDIyD/C8k9jeTBjivlURlS2iRVS0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FrdjML%2FbtsNrcyDIyD%2FC8k9jeTBjivlURlS2iRVS0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;2000&quot; height=&quot;1125&quot; data-filename=&quot;슬라이드22.PNG&quot; data-origin-width=&quot;2000&quot; data-origin-height=&quot;1125&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그리고 D[2]를 보면 D[2] = D[1] + D[0]에서 D[1]에 대응되는 경우는 1원을 만드는 방법에다가 1원짜리 동전을 추가한거니 1+1이고&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;슬라이드23.PNG&quot; data-origin-width=&quot;2000&quot; data-origin-height=&quot;1125&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/c4cEM5/btsNsmnsLkv/rmVeTGMAFiFHJkeD2idjUk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/c4cEM5/btsNsmnsLkv/rmVeTGMAFiFHJkeD2idjUk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/c4cEM5/btsNsmnsLkv/rmVeTGMAFiFHJkeD2idjUk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fc4cEM5%2FbtsNsmnsLkv%2FrmVeTGMAFiFHJkeD2idjUk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;2000&quot; height=&quot;1125&quot; data-filename=&quot;슬라이드23.PNG&quot; data-origin-width=&quot;2000&quot; data-origin-height=&quot;1125&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;D[0]에 대응되는 경우는 0원을 만드는 방법에 2원짜리 동전을 추가한 것이므로 2가 대응됩니다. 이렇게 1 + 1과 2 두 가지 방법이 존재하니, D[2] = 2가 맞습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;슬라이드24.PNG&quot; data-origin-width=&quot;2000&quot; data-origin-height=&quot;1125&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/0kMXW/btsNr7KjN3W/q7KoWQfImkYDIbKA0JAIk1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/0kMXW/btsNr7KjN3W/q7KoWQfImkYDIbKA0JAIk1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/0kMXW/btsNr7KjN3W/q7KoWQfImkYDIbKA0JAIk1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F0kMXW%2FbtsNr7KjN3W%2Fq7KoWQfImkYDIbKA0JAIk1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;2000&quot; height=&quot;1125&quot; data-filename=&quot;슬라이드24.PNG&quot; data-origin-width=&quot;2000&quot; data-origin-height=&quot;1125&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다음으로 D[3] = D[2] + D[1]이라는 식에서, D[2]는 2원을 만드는 방법에 1원짜리 동전을 추가하는 경우이므로 1원짜리 3개와 2원 1개, 1원 1개를 쓰는 방법 이 2가지에 해당합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;슬라이드25.PNG&quot; data-origin-width=&quot;2000&quot; data-origin-height=&quot;1125&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/ntL1M/btsNsjqZdd6/vM9LlI7kGMNeSQvyLViVfk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/ntL1M/btsNsjqZdd6/vM9LlI7kGMNeSQvyLViVfk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/ntL1M/btsNsjqZdd6/vM9LlI7kGMNeSQvyLViVfk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FntL1M%2FbtsNsjqZdd6%2FvM9LlI7kGMNeSQvyLViVfk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;2000&quot; height=&quot;1125&quot; data-filename=&quot;슬라이드25.PNG&quot; data-origin-width=&quot;2000&quot; data-origin-height=&quot;1125&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그리고 D[1]은 1원을 만드는 방법에 2원짜리 동전을 추가하는 경우여서 1원짜리 1개와 2원짜리 1개를 쓰는 경우를 D[3]에 더하겠다는 것인데, 이제 명확하게 현재의 DP 식이 틀린 이유가 무엇인지 감이 오실 겁니다. 이 지점이 사실 이 문제와 9095번 문제의 차이점이기도 합니다. 9095번 문제에서는 1 + 2와 2 + 1을 다른 경우로 분류하지만 이 문제에서는 1 + 2와 2 + 1은 모두 1원짜리 1개와 2원짜리 1개를 쓰는 경우로 취급됩니다. 그래서 현재의 DP 식이 틀린 이유는 이 식대로 진행하면 1 + 2와 2 + 1을 다른 경우로 취급하게 되기 때문입니다. 그러므로 다시 초심으로 돌아가서 테이블과 점화식을 새로 정해봐야 할 필요가 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;슬라이드26.PNG&quot; data-origin-width=&quot;2000&quot; data-origin-height=&quot;1125&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/GF5ot/btsNslbhSz6/ksDTshjzMhrRckKD1kTQ9k/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/GF5ot/btsNslbhSz6/ksDTshjzMhrRckKD1kTQ9k/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/GF5ot/btsNslbhSz6/ksDTshjzMhrRckKD1kTQ9k/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FGF5ot%2FbtsNslbhSz6%2FksDTshjzMhrRckKD1kTQ9k%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;2000&quot; height=&quot;1125&quot; data-filename=&quot;슬라이드26.PNG&quot; data-origin-width=&quot;2000&quot; data-origin-height=&quot;1125&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;기존의 테이블과 식에서는 동전을 추가하는 순서가 중구난방이었습니다. 예를 들어 1원짜리도 추가했다가 2원짜리도 추가했다가 이런 식으로 하면 앞서 본 것처럼 1+2와 2+1을 자칫 다른 경우로 세버릴 수 있습니다. 이를 해결하기 위한 좋은 방법은 첫 번째 동전만을 이용해 0원부터 M원까지를 채운 후, 그다음 두 번째 동전을 추가하는 식으로 동전을 순차적으로 적용하는 방법입니다. 이렇게 하면 2+1과 같은 경우는 경우의 수에 포함되지 않게 됩니다. 즉 1원을 쓴 후에 2원을 써야 하므로 동전 사용 순서를 강제하게 되어 같은 방법을 여러 경우로 세는 것을 방지할 수 있습니다. 그래서 테이블을 1차원으로 만드는 대신, &quot;i번째 동전까지 썼을 때&quot;라는 조건을 추가하여 2차원 테이블로 만들게 됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;슬라이드27.PNG&quot; data-origin-width=&quot;2000&quot; data-origin-height=&quot;1125&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bpqrYQ/btsNsRmZWMr/aaAKtdSfZx0OAcSIqb4yBK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bpqrYQ/btsNsRmZWMr/aaAKtdSfZx0OAcSIqb4yBK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bpqrYQ/btsNsRmZWMr/aaAKtdSfZx0OAcSIqb4yBK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbpqrYQ%2FbtsNsRmZWMr%2FaaAKtdSfZx0OAcSIqb4yBK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;2000&quot; height=&quot;1125&quot; data-filename=&quot;슬라이드27.PNG&quot; data-origin-width=&quot;2000&quot; data-origin-height=&quot;1125&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다음으로 식을 찾아야 하는데, i번째 동전을 몇 개 썼냐를 가지고 이렇게 접근할 수 있습니다. i번째 동전을 사용한 개수를 지정한 후, 나머지 금액은 i-1번째 동전까지만으로 해결해야 하므로 자연스럽게 식을 도출할 수 있습니다. 예를 들어 i번째 동전을 1개 썼다면 j - c[i]원을 i-1번째 동전까지만으로 채워야 하기 때문에 식은 D[i - 1][j - c[i]]가 됩니다. 이 방식으로 점화식을 유도할 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;슬라이드28.PNG&quot; data-origin-width=&quot;2000&quot; data-origin-height=&quot;1125&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/Ev4yZ/btsNslh5dGF/tyTm8avNdO5Gg6ZoCcwlm1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/Ev4yZ/btsNslh5dGF/tyTm8avNdO5Gg6ZoCcwlm1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/Ev4yZ/btsNslh5dGF/tyTm8avNdO5Gg6ZoCcwlm1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FEv4yZ%2FbtsNslh5dGF%2FtyTm8avNdO5Gg6ZoCcwlm1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;2000&quot; height=&quot;1125&quot; data-filename=&quot;슬라이드28.PNG&quot; data-origin-width=&quot;2000&quot; data-origin-height=&quot;1125&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;227&quot; data-start=&quot;0&quot; data-ke-size=&quot;size16&quot;&gt;그리고 여기서 한 단계 더 발전시켜서 식을 더 간단하게 줄일 수 있는데, i번째 동전을 쓰는지 안 쓰는지로만 나누면 됩니다. i번째 동전을 안 쓴 경우는 당연히 D[i-1][j]이고, 1개 이상 쓴 경우는 i번째 동전을 먼저 1개 써서 전체 j원 중 c[i]원을 해결하고, 나머지 j - c[i]원을 채울 때 1번부터 i-1번째 동전까지를 쓰는 게 아니라 1번부터 i번째 동전까지 모두 쓸 수 있습니다.&lt;/p&gt;
&lt;p data-end=&quot;227&quot; data-start=&quot;0&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;432&quot; data-start=&quot;229&quot; data-ke-size=&quot;size16&quot;&gt;따라서 이전처럼 i번째 동전을 1개 썼다, 2개 썼다 이렇게 경우를 나눌 필요 없이, 1개 이상 쓴 경우는 D[i][j - c[i]]로 표현할 수 있습니다. 이렇게 되면 c[i]가 1일 때 아까는 j+1개의 값을 더해야 D[i][j]를 구할 수 있었지만, 지금은 j와 c[i]의 값에 관계없이 2칸만 더하면 되므로 시간 복잡도를 더 효율적으로 줄일 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;슬라이드29.PNG&quot; data-origin-width=&quot;2000&quot; data-origin-height=&quot;1125&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/boZW5r/btsNslbhSEN/7VTIRiwab36QVyJCXxMs31/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/boZW5r/btsNslbhSEN/7VTIRiwab36QVyJCXxMs31/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/boZW5r/btsNslbhSEN/7VTIRiwab36QVyJCXxMs31/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FboZW5r%2FbtsNslbhSEN%2F7VTIRiwab36QVyJCXxMs31%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;2000&quot; height=&quot;1125&quot; data-filename=&quot;슬라이드29.PNG&quot; data-origin-width=&quot;2000&quot; data-origin-height=&quot;1125&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;여기서 한 가지 분명히 말씀드리고 싶은 점은, 이 점화식이 조금 어려운 건 맞습니다. 직관적으로 식이 잘 안 보일 수도 있고, 심지어 앞의 설명을 듣고도 이게 맞나 하고 잘 납득이 안 가는 게 매우 정상입니다. 이해를 돕기 위해 점화식이 맞는지 헷갈릴 때 확인할 수 있는 방법을 알려드리면, D[i][j]에 대응되는 경우의 수 중에서 해당 점화식이 혹시 빼먹은 케이스가 있는지, 아니면 점화식에서 중복으로 센 게 있는지를 고민해볼 수 있습니다. 그렇게 반례를 만들려고 고민하다 보면, &quot;아, 정말로 지금의 식이 D[i][j]에 대한 모든 경우를 다 포함하는구나&quot; 하고 납득할 수 있을 것입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;슬라이드30.PNG&quot; data-origin-width=&quot;2000&quot; data-origin-height=&quot;1125&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bQpT0Q/btsNr1J6ZNW/bw7ghKpOdV0x13jWa7X2xK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bQpT0Q/btsNr1J6ZNW/bw7ghKpOdV0x13jWa7X2xK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bQpT0Q/btsNr1J6ZNW/bw7ghKpOdV0x13jWa7X2xK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbQpT0Q%2FbtsNr1J6ZNW%2Fbw7ghKpOdV0x13jWa7X2xK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;2000&quot; height=&quot;1125&quot; data-filename=&quot;슬라이드30.PNG&quot; data-origin-width=&quot;2000&quot; data-origin-height=&quot;1125&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;초기값을 설정하는 방법은 간단합니다. 각 i에서 0원을 만드는 방법은 1가지로 정의하면 됩니다. 즉, D[i][0] = 1입니다. 그리고 테이블을 채울 때는 LCS 문제처럼 i 순으로, 그리고 각 i에서 j 순으로 채우면 됩니다. 이 방법으로 구현을 진행하면 됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;슬라이드31.PNG&quot; data-origin-width=&quot;2000&quot; data-origin-height=&quot;1125&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/2Ywf0/btsNr9Wvvde/4yITIDuAtFUAtnIEKM0fp0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/2Ywf0/btsNr9Wvvde/4yITIDuAtFUAtnIEKM0fp0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/2Ywf0/btsNr9Wvvde/4yITIDuAtFUAtnIEKM0fp0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F2Ywf0%2FbtsNr9Wvvde%2F4yITIDuAtFUAtnIEKM0fp0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;2000&quot; height=&quot;1125&quot; data-filename=&quot;슬라이드31.PNG&quot; data-origin-width=&quot;2000&quot; data-origin-height=&quot;1125&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;구현은 적당히 잘 하시면 되고, 점화식 자체는 d[i][j] = d[i-1][j] + d[i][j-coin[i]]입니다. 하지만 실제로 코딩할 때는 22~27번째 줄에서 작성한 것처럼 인덱스가 음수로 가지 않도록 주의해야 합니다. 또한 이 문제와 관련하여 한 가지 더 말씀드릴 점이 있는데, 다른 사람들의 풀이를 보다 보면 2차원 배열을 사용하지 않고 1차원 배열로 풀어낸 코드를 볼 수 있습니다. 제 코드와 동일한 점화식을 사용하되, d를 d[22][10002] 대신 d[10002]로 사용해도 해결이 가능한데, 이 기법을 토글링이라고 합니다. 토글링을 알면 당연히 유용하지만, 이 기법은 공간 복잡도를 줄일 수는 있지만 시간 복잡도는 그대로이고, 일반적으로 공간 복잡도보다 시간 복잡도가 더 중요한 경우가 많기 때문에 이번 강의에서는 토글링에 대해서 별도로 설명하지 않습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;혹시 풀이를 찾아보다가 1차원 배열을 사용한 코드를 보고 이건 어떻게 한 거지? 라는 의문이 들 수 있기 때문에 언급한 것이며, 점화식 자체는 동일하기 때문에 굳이 신경 쓸 필요는 없습니다. &lt;a href=&quot;https://github.com/encrypted-def/basic-algo-lecture/blob/master/Appendix%20E/9084.cpp&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;(코드)&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;슬라이드32.PNG&quot; data-origin-width=&quot;2000&quot; data-origin-height=&quot;1125&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/brb7Nu/btsNsmueyXq/YnLaQ3ojhGROjkUEtyyKm0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/brb7Nu/btsNsmueyXq/YnLaQ3ojhGROjkUEtyyKm0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/brb7Nu/btsNsmueyXq/YnLaQ3ojhGROjkUEtyyKm0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fbrb7Nu%2FbtsNsmueyXq%2FYnLaQ3ojhGROjkUEtyyKm0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;2000&quot; height=&quot;1125&quot; data-filename=&quot;슬라이드32.PNG&quot; data-origin-width=&quot;2000&quot; data-origin-height=&quot;1125&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;191&quot; data-start=&quot;0&quot; data-ke-size=&quot;size16&quot;&gt;두 번째 문제는 &lt;a href=&quot;https://www.acmicpc.net/problem/12865&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;BOJ 12865번: 평범한 배낭&lt;/a&gt; 문제입니다. 그리디 단원에서 이 문제를 그리디 알고리즘으로 풀면 반례가 있다는 내용을 소개한 적이 있는데, 이 문제는 다이나믹 프로그래밍을 통해 해결할 수 있습니다. 여기서 이 문제의 느낌이 앞의 문제와 비슷하다는 생각을 하셨다면, 상당히 센스가 있다고 할 수 있겠습니다. 혹시 그런 느낌을 받으셨나요?&lt;/p&gt;
&lt;p data-end=&quot;447&quot; data-start=&quot;193&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;447&quot; data-start=&quot;193&quot; data-ke-size=&quot;size16&quot;&gt;이 문제에서도 단순히 직관적으로 d[j]를 무게가 j일 때의 최대 가치라고 정의한다고 해도, 식을 세울 방법이 쉽게 떠오르지 않습니다. i번째 물건의 무게와 가치를 각각 W[i], V[i]로 두었을 때, d[j] = d[j - W[i]] + V[i]와 같은 형태로, i번째 물건을 선택했을 때의 상황을 식으로 표현할 수 있을 것 같지만 이 식을 바탕으로 d[0]부터 채워나가려고 하면 각 물건은 1개만 있다는 조건을 추가할 방법이 없습니다. 이 상황은 저번 문제에서의 상황과 유사하고 해결책도 비슷합니다. 테이블을 2차원으로 두고 i번째 물건까지 고려했을 때의 최대 가치를 관리하는 방식으로 문제를 풀 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;슬라이드33.PNG&quot; data-origin-width=&quot;2000&quot; data-origin-height=&quot;1125&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/kxLsf/btsNsmactZF/gAypk83H98KQDSkSuOX6Z0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/kxLsf/btsNsmactZF/gAypk83H98KQDSkSuOX6Z0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/kxLsf/btsNsmactZF/gAypk83H98KQDSkSuOX6Z0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FkxLsf%2FbtsNsmactZF%2FgAypk83H98KQDSkSuOX6Z0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;2000&quot; height=&quot;1125&quot; data-filename=&quot;슬라이드33.PNG&quot; data-origin-width=&quot;2000&quot; data-origin-height=&quot;1125&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;따라서 테이블을 D[i][j] = i번째 물건까지 고려했을 때, 무게 j로 만들 수 있는 최대 가치로 정의합니다. 그다음 점화식을 찾아 초기값을 설정하고 순서를 정해야 하는데, 앞서 푼 문제의 느낌을 살려서 직접 시도해보는 것을 권장합니다. 구현까지 한번 도전해보셔도 좋습니다. 저는 다음 슬라이드에서 설명을 계속 이어가겠습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;슬라이드34.PNG&quot; data-origin-width=&quot;2000&quot; data-origin-height=&quot;1125&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/FnDEg/btsNrXosgpS/kjuQcUF5bANqArnwemxzwk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/FnDEg/btsNrXosgpS/kjuQcUF5bANqArnwemxzwk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/FnDEg/btsNrXosgpS/kjuQcUF5bANqArnwemxzwk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FFnDEg%2FbtsNrXosgpS%2FkjuQcUF5bANqArnwemxzwk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;2000&quot; height=&quot;1125&quot; data-filename=&quot;슬라이드34.PNG&quot; data-origin-width=&quot;2000&quot; data-origin-height=&quot;1125&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;228&quot; data-start=&quot;0&quot; data-ke-size=&quot;size16&quot;&gt;점화식을 보면 D[i][j]를 구할 때 i번째 물건을 사용한 경우와 사용하지 않은 경우로 나눌 수 있습니다. i번째 물건을 사용한 경우, 즉 i-1번째 물건까지 고려했을 때 j-W[i]의 무게를 만들 수 있는 최대 가치에 i번째 물건의 가치를 더한 값이 됩니다. 이때 가치는 D[i-1][j-W[i]] + V[i]가 됩니다. 반대로 i번째 물건을 사용하지 않았다면, 그저 D[i-1][j]를 가져오면 됩니다.&lt;/p&gt;
&lt;p data-end=&quot;228&quot; data-start=&quot;0&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;357&quot; data-start=&quot;230&quot; data-ke-size=&quot;size16&quot;&gt;초기값은 각 i에 대해 D[i][0] = 0으로 두면 되고, D[i][j]를 채울 때 필요한 값들이 모두 왼쪽 혹은 위쪽에 위치하므로 테이블을 채우는 순서는 특별히 고민할 필요 없이 이중 for문을 돌며 차례대로 채우면 됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;슬라이드35.PNG&quot; data-origin-width=&quot;2000&quot; data-origin-height=&quot;1125&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/mBv01/btsNr8oV7G0/Vt89ONNsvHZyeQJ7xjP9g1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/mBv01/btsNr8oV7G0/Vt89ONNsvHZyeQJ7xjP9g1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/mBv01/btsNr8oV7G0/Vt89ONNsvHZyeQJ7xjP9g1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FmBv01%2FbtsNr8oV7G0%2FVt89ONNsvHZyeQJ7xjP9g1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;2000&quot; height=&quot;1125&quot; data-filename=&quot;슬라이드35.PNG&quot; data-origin-width=&quot;2000&quot; data-origin-height=&quot;1125&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;160&quot; data-start=&quot;57&quot; data-ke-size=&quot;size16&quot;&gt;역시 마찬가지로 배열 인덱스가 음수로 가지 않게 주의해서 구현을 하면 되고, 전역 변수를 사용하면 0이 기본값으로 들어간다는 점을 인지한 상태로 코드를 보면 이해에 도움이 될 것입니다. &lt;a href=&quot;https://github.com/encrypted-def/basic-algo-lecture/blob/master/Appendix%20E/12865.cpp&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;(코드)&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;슬라이드36.PNG&quot; data-origin-width=&quot;2000&quot; data-origin-height=&quot;1125&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bQLcMT/btsNs47qHyt/3lNHthkx6vyttK0dsQbsW0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bQLcMT/btsNs47qHyt/3lNHthkx6vyttK0dsQbsW0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bQLcMT/btsNs47qHyt/3lNHthkx6vyttK0dsQbsW0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbQLcMT%2FbtsNs47qHyt%2F3lNHthkx6vyttK0dsQbsW0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;2000&quot; height=&quot;1125&quot; data-filename=&quot;슬라이드36.PNG&quot; data-origin-width=&quot;2000&quot; data-origin-height=&quot;1125&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;마지막으로 다룰 문제는 BOJ 1915번: 가장 큰 정사각형입니다. 이 문제는 지금까지 다룬 문제들과는 약간 다른 성격을 가지고 있어서 만약 비슷한 문제를 본 적이 없다면 풀이 방법을 쉽게 떠올리기 어려울 수 있습니다. 이 문제에서는 풀이 접근 방식에 너무 매몰될 필요가 없고 그냥 풀이를 바로 확인한 다음 비슷한 문제가 나왔을 때 비슷한 느낌으로 접근을 해야겠다 정도의 깨달음을 얻고 가면 충분합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;슬라이드37.PNG&quot; data-origin-width=&quot;2000&quot; data-origin-height=&quot;1125&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/z1pGM/btsNruseo4i/GXBnTxQHWQuhs0HQKvXk71/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/z1pGM/btsNruseo4i/GXBnTxQHWQuhs0HQKvXk71/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/z1pGM/btsNruseo4i/GXBnTxQHWQuhs0HQKvXk71/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fz1pGM%2FbtsNruseo4i%2FGXBnTxQHWQuhs0HQKvXk71%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;2000&quot; height=&quot;1125&quot; data-filename=&quot;슬라이드37.PNG&quot; data-origin-width=&quot;2000&quot; data-origin-height=&quot;1125&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그래서 바로 테이블의 정의를 보면 D[i][j]를 위에서 언급한 것처럼 정의합니다. 이해를 돕기 위해 예시를 하나 가져왔습니다. 예를 들어 D[3][3]을 생각하면 크기가 3인 정사각형을 만들 수 있으니 D[3][3] = 3이 됩니다. 나머지 값들도 눈으로 한번 쓱 보면 그렇게 어렵지 않게 값이 맞는지 확인할 수 있을 겁니다. 왜 테이블을 이런 형태로 정의하는지 궁금할 수 있지만 앞에서 말한 것처럼 그 발상 과정을 이해하려고 하기보다는, 그냥 테이블을 이렇게 잡으니 문제가 풀리더라는 점을 받아들이고 일단 넘어가는 것이 좋습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;슬라이드38.PNG&quot; data-origin-width=&quot;2000&quot; data-origin-height=&quot;1125&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/6H18i/btsNsieznTe/3qDa71HNKA7JZnMYmxTff0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/6H18i/btsNsieznTe/3qDa71HNKA7JZnMYmxTff0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/6H18i/btsNsieznTe/3qDa71HNKA7JZnMYmxTff0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F6H18i%2FbtsNsieznTe%2F3qDa71HNKA7JZnMYmxTff0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;2000&quot; height=&quot;1125&quot; data-filename=&quot;슬라이드38.PNG&quot; data-origin-width=&quot;2000&quot; data-origin-height=&quot;1125&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;테이블을 정했으니 이제 점화식을 잘 찾기만 하면 끝인데 그게 참 어렵습니다. 이 문제에서 점화식을 찾으려면 LCS 문제와 약간 비슷한 느낌으로 D[i][j]가 특정 값일 때의 형태를 생각하면서 어떻게 다른 테이블의 값을 이용할 수 있을지를 고민해야 합니다. 물론 말이 쉽지, 이렇게 말하면 무슨 소린지 하나도 이해가 안 갈 수도 있습니다. 그래서 발상을 조금 도와드리기 위해 그림을 하나 준비했습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;슬라이드39.PNG&quot; data-origin-width=&quot;2000&quot; data-origin-height=&quot;1125&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dGKUku/btsNsGFIKOd/0jgYZSBRQ6U4RulcgPjyDk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dGKUku/btsNsGFIKOd/0jgYZSBRQ6U4RulcgPjyDk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dGKUku/btsNsGFIKOd/0jgYZSBRQ6U4RulcgPjyDk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdGKUku%2FbtsNsGFIKOd%2F0jgYZSBRQ6U4RulcgPjyDk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;2000&quot; height=&quot;1125&quot; data-filename=&quot;슬라이드39.PNG&quot; data-origin-width=&quot;2000&quot; data-origin-height=&quot;1125&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;D 테이블에서 어느 칸 (i, j)의 값이 k라고 가정해봅시다. 그러면 그 칸을 오른쪽 아래 모서리로 두는 길이가 k인 정사각형이 존재한다는 뜻입니다. 즉, D[i][j]의 값은 해당 위치에서 끝나는 정사각형의 크기를 나타내는 것이죠.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;슬라이드40.PNG&quot; data-origin-width=&quot;2000&quot; data-origin-height=&quot;1125&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/GVKFz/btsNpUkTte7/DHQTzKkayHEz3jukQJ3Rb0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/GVKFz/btsNpUkTte7/DHQTzKkayHEz3jukQJ3Rb0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/GVKFz/btsNpUkTte7/DHQTzKkayHEz3jukQJ3Rb0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FGVKFz%2FbtsNpUkTte7%2FDHQTzKkayHEz3jukQJ3Rb0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;2000&quot; height=&quot;1125&quot; data-filename=&quot;슬라이드40.PNG&quot; data-origin-width=&quot;2000&quot; data-origin-height=&quot;1125&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;D 테이블에서 어느 칸 (i, j)의 값이 k라면 그 칸을 오른쪽 아래 모서리로 두는 길이가 k인 정사각형이 있다는 뜻입니다. 주황색으로 표시한 영역은 D[i][j-1]의 값과 관련이 있습니다. 주황색 영역의 오른쪽 아래가 (i, j-1)이기 때문입니다. D[i][j] = k라면 D[i][j-1]은 최소 k-1이어야 합니다. 값이 k-1보다 더 클 수도 있다는 점을 꼭 유념하고,&amp;nbsp; 다음 그림을 보겠습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;슬라이드41.PNG&quot; data-origin-width=&quot;2000&quot; data-origin-height=&quot;1125&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/0maIK/btsNtfVvxaV/iGNRad9NHt51Of53C51L70/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/0maIK/btsNtfVvxaV/iGNRad9NHt51Of53C51L70/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/0maIK/btsNtfVvxaV/iGNRad9NHt51Of53C51L70/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F0maIK%2FbtsNtfVvxaV%2FiGNRad9NHt51Of53C51L70%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;2000&quot; height=&quot;1125&quot; data-filename=&quot;슬라이드41.PNG&quot; data-origin-width=&quot;2000&quot; data-origin-height=&quot;1125&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다음으로는 D[i-1][j]와 관련 있는 영역을 가져왔습니다. 같은 논리로 따지면 D[i-1][j]도 k-1 이상이어야 합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;슬라이드42.PNG&quot; data-origin-width=&quot;2000&quot; data-origin-height=&quot;1125&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/lhlIY/btsNrwdzSSs/gnofSWW15hQXGXWHuFIGbk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/lhlIY/btsNrwdzSSs/gnofSWW15hQXGXWHuFIGbk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/lhlIY/btsNrwdzSSs/gnofSWW15hQXGXWHuFIGbk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FlhlIY%2FbtsNrwdzSSs%2FgnofSWW15hQXGXWHuFIGbk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;2000&quot; height=&quot;1125&quot; data-filename=&quot;슬라이드42.PNG&quot; data-origin-width=&quot;2000&quot; data-origin-height=&quot;1125&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;마지막으로 D[i-1][j-1]도 마찬가지 논리로 k-1 이상입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;슬라이드43.PNG&quot; data-origin-width=&quot;2000&quot; data-origin-height=&quot;1125&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cn4M7j/btsNsiMq9eN/VOwmRbX115imlUjuLTfof0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cn4M7j/btsNsiMq9eN/VOwmRbX115imlUjuLTfof0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cn4M7j/btsNsiMq9eN/VOwmRbX115imlUjuLTfof0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fcn4M7j%2FbtsNsiMq9eN%2FVOwmRbX115imlUjuLTfof0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;2000&quot; height=&quot;1125&quot; data-filename=&quot;슬라이드43.PNG&quot; data-origin-width=&quot;2000&quot; data-origin-height=&quot;1125&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;지금까지 얘기한 내용을 한데 모아보면, D[i][j] = k일 때 D[i][j-1], D[i-1][j], D[i-1][j-1] 이 3개 칸의 값은 반드시 k-1 이상입니다. 그럼 여기서 점화식을 확정짓기 위해 추가로 생각해봐야 하는 것은 D[i][j-1], D[i-1][j], D[i-1][j-1]의 최솟값이 k-1일 때 D[i][j]는 k가 되는지 여부입니다. 머릿속으로 상황을 생각해보면 그렇게 어렵지 않게 맞다는 걸 알 수 있습니다. 일단 (i, j) 칸이 1일 때 세 노란색 영역을 합치면 (i, j)를 오른쪽 아래로 두는 크기 k짜리 정사각형이 다 채워지게 됩니다. 그러니까 D[i][j]는 k 이상인 게 맞고, 여기서 추가로 값을 확정하려면 D[i][j]가 k보다 클 가능성은 없다는 것을 봐야하는데 이건 직관적으로 이해할 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;슬라이드44.PNG&quot; data-origin-width=&quot;2000&quot; data-origin-height=&quot;1125&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/qLORQ/btsNsPXgNPo/Kyw9KPT7D1FuMwwK4ZNZ81/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/qLORQ/btsNsPXgNPo/Kyw9KPT7D1FuMwwK4ZNZ81/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/qLORQ/btsNsPXgNPo/Kyw9KPT7D1FuMwwK4ZNZ81/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FqLORQ%2FbtsNsPXgNPo%2FKyw9KPT7D1FuMwwK4ZNZ81%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;2000&quot; height=&quot;1125&quot; data-filename=&quot;슬라이드44.PNG&quot; data-origin-width=&quot;2000&quot; data-origin-height=&quot;1125&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;예를 들어 D[i][j]가 k보다 커서 (i, j)를 오른쪽 아래로 하는 크기 k+1의 정사각형이 있다고 가정해 봅시다. 그러면 그림에서 볼 수 있듯이 D[i][j-1], D[i-1][j], D[i-1][j-1]이 모두 k 이상이므로, D[i][j-1], D[i-1][j], D[i-1][j-1]의 최솟값은 k-1이라는 처음의 가정과 모순이 발생하게 됩니다. 따라서 D[i][j]는 k보다 클 수 없고, 앞에서 확인한 대로 D[i][j]가 k 이상인 것은 맞으므로 종합적으로 보면 D[i][j-1], D[i-1][j], D[i-1][j-1]의 최솟값이 k-1일 때 D[i][j]가 k라는 결론을 얻을 수 있습니다. 이를 바탕으로 점화식을 세울 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;슬라이드45.PNG&quot; data-origin-width=&quot;2000&quot; data-origin-height=&quot;1125&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/zACxq/btsNsTSFpKs/qLhUUTQFqqnIKG0HvH9TKK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/zACxq/btsNsTSFpKs/qLhUUTQFqqnIKG0HvH9TKK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/zACxq/btsNsTSFpKs/qLhUUTQFqqnIKG0HvH9TKK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FzACxq%2FbtsNsTSFpKs%2FqLhUUTQFqqnIKG0HvH9TKK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;2000&quot; height=&quot;1125&quot; data-filename=&quot;슬라이드45.PNG&quot; data-origin-width=&quot;2000&quot; data-origin-height=&quot;1125&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;식은 이렇게 나눌 수 있습니다. 우선 (i, j) 칸이 0인지 1인지에 따라 다르게 처리합니다. 만약 (i, j) 칸이 0이면 고민할 필요 없이 바로 D[i][j]를 0으로 두면 됩니다. 반면 (i, j) 칸이 1이라면 D[i-1][j], D[i][j-1], D[i-1][j-1] 이 세 칸의 값을 확인하고 그 중 최솟값을 구한 후, 그 값에 1을 더한 값이 D[i][j]가 됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;슬라이드46.PNG&quot; data-origin-width=&quot;2000&quot; data-origin-height=&quot;1125&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cFIaGg/btsNrZzP2gh/k2KDCBlf5pNu7cS7YJQIqK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cFIaGg/btsNrZzP2gh/k2KDCBlf5pNu7cS7YJQIqK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cFIaGg/btsNrZzP2gh/k2KDCBlf5pNu7cS7YJQIqK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcFIaGg%2FbtsNrZzP2gh%2Fk2KDCBlf5pNu7cS7YJQIqK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;2000&quot; height=&quot;1125&quot; data-filename=&quot;슬라이드46.PNG&quot; data-origin-width=&quot;2000&quot; data-origin-height=&quot;1125&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다음으로 초기값을 설정하는 데 있어 특별히 어려운 부분은 없습니다. D[i-1][j], D[i-1][j-1], D[i][j-1] 칸들이 잘 정의되지 않는 가장 윗쪽과 왼쪽의 칸들에 대해서 미리 값을 채워주면 됩니다. 테이블을 채우는 순서도 일반적인 방식대로, 즉 위에서 아래로 / 왼쪽에서 오른쪽으로 채워주면 됩니다. 이제 구현을 진행하면 됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;슬라이드47.PNG&quot; data-origin-width=&quot;2000&quot; data-origin-height=&quot;1125&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bu34Tq/btsNtgtkebW/yEODWj88Dd0IOD5Qy5q9X0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bu34Tq/btsNtgtkebW/yEODWj88Dd0IOD5Qy5q9X0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bu34Tq/btsNtgtkebW/yEODWj88Dd0IOD5Qy5q9X0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fbu34Tq%2FbtsNtgtkebW%2FyEODWj88Dd0IOD5Qy5q9X0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;2000&quot; height=&quot;1125&quot; data-filename=&quot;슬라이드47.PNG&quot; data-origin-width=&quot;2000&quot; data-origin-height=&quot;1125&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 문제가 DP 식을 찾아내는 것이 어려운 건 맞지만, 구현은 별다를 것이 없습니다. 앞에서 살펴본 내용을 그대로 코드로 옮기면 됩니다. 이 문제를 통해 테이블을 정의하는 방법을 새롭게 배운 셈인데, 사실 이 방법이 완전히 새로운 것은 아닙니다. &lt;a href=&quot;https://www.acmicpc.net/problem/8958&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;BOJ 8958번: OX 퀴즈&lt;/a&gt;와 비슷한 느낌으로 &quot;OOXXOOXOO&quot;라는 문자열이 주어졌을 때 연속된 O의 최대 길이를 구하는 문제를 풀 때, 해당 글자가 끝나는 연속된 O의 최대 길이를 구하는 방법으로 점화식을 세울 수 있습니다. 이 문제는 그 방식을 2차원 배열로 확장한 문제입니다. 앞으로 비슷한 문제를 만나면 이 문제에서 테이블과 점화식이 어떻게 정의되었는지 떠올려보는걸 추천드립니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;슬라이드48.PNG&quot; data-origin-width=&quot;2000&quot; data-origin-height=&quot;1125&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/pO57b/btsNspxMpmb/yGAVkEKYG48z8VtpGqdRW1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/pO57b/btsNspxMpmb/yGAVkEKYG48z8VtpGqdRW1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/pO57b/btsNspxMpmb/yGAVkEKYG48z8VtpGqdRW1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FpO57b%2FbtsNspxMpmb%2FyGAVkEKYG48z8VtpGqdRW1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;2000&quot; height=&quot;1125&quot; data-filename=&quot;슬라이드48.PNG&quot; data-origin-width=&quot;2000&quot; data-origin-height=&quot;1125&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;204&quot; data-start=&quot;0&quot; data-ke-size=&quot;size16&quot;&gt;네, 상당히 많은걸 한 것 같은데 이제 2차원 DP 챕터 하나가 끝났네요. 계속 달려봅시다. 이번 챕터는 top-down DP에 대한 내용입니다. DP를 풀 때는 테이블을 정의하고, 점화식을 찾고, 초기값을 정하는 과정이 필요합니다. 이 세 가지는 초반 강의에서 언급된 내용인데, 여기에 하나를 더 추가하자면 테이블을 채우는 순서도 잘 정해야 한다는 점입니다.&lt;/p&gt;
&lt;p data-end=&quot;204&quot; data-start=&quot;0&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;204&quot; data-start=&quot;0&quot; data-ke-size=&quot;size16&quot;&gt;기본적으로 1차원 DP에서는 거의 다 가장 작은 인덱스부터 혹은 가장 큰 인덱스부터 채우면 되기 때문에 크게 복잡할 게 없었지만, 2차원 DP에서는 초기값을 정하고 테이블을 채우는 순서를 정하는 것이 조금 헷갈릴 수 있습니다. 이 점이 bottom-up 방식의 단점입니다. 앞서 살펴본 DAG에서 간선끼리의 선후 관계에 문제가 없도록 채우는 순서를 신중하게 설정해야 합니다. 만약 채우는 순서를 어렵지 않게 정할 수 있다면 계속해서 bottom-up 방식으로 해결할 수 있습니다. 반면 테이블과 점화식은 잘 보이지만 채우는 순서가 까다롭다면 top-down 방식을 고려해볼 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;슬라이드49.PNG&quot; data-origin-width=&quot;2000&quot; data-origin-height=&quot;1125&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bGq7P9/btsNrzOSaTj/O0aycLMjRKeK2uh2QqzShK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bGq7P9/btsNrzOSaTj/O0aycLMjRKeK2uh2QqzShK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bGq7P9/btsNrzOSaTj/O0aycLMjRKeK2uh2QqzShK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbGq7P9%2FbtsNrzOSaTj%2FO0aycLMjRKeK2uh2QqzShK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;2000&quot; height=&quot;1125&quot; data-filename=&quot;슬라이드49.PNG&quot; data-origin-width=&quot;2000&quot; data-origin-height=&quot;1125&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;top-down 방식은 이름에서 유추할 수 있듯이, 위에서부터 시작해 내려오는 방식을 의미합니다. DP에서 이것이 어떤 것을 의미하는지 이해하기 위해 피보나치 수열을 예로 들어보겠습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;슬라이드50.PNG&quot; data-origin-width=&quot;2000&quot; data-origin-height=&quot;1125&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/lVzex/btsNtcEsH92/Zdf9kBL81ntwhBKrrgDnb1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/lVzex/btsNtcEsH92/Zdf9kBL81ntwhBKrrgDnb1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/lVzex/btsNtcEsH92/Zdf9kBL81ntwhBKrrgDnb1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FlVzex%2FbtsNtcEsH92%2FZdf9kBL81ntwhBKrrgDnb1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;2000&quot; height=&quot;1125&quot; data-filename=&quot;슬라이드50.PNG&quot; data-origin-width=&quot;2000&quot; data-origin-height=&quot;1125&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;피보나치 수열을 bottom-up 방식으로 구할 때에는 f[0], f[1]이 초기값이 되고, 그 후 f[2]부터 차례대로 값을 계산하여 넣습니다. 즉, bottom-up 방식에서는 밑에서부터 값을 하나씩 채워가며 위로 올라갑니다. 반면, top-down 방식으로 해결할 때의 코드는 어떻게 작성되는지 살펴보겠습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;슬라이드51.PNG&quot; data-origin-width=&quot;2000&quot; data-origin-height=&quot;1125&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bhKxYw/btsNqqcPAp0/0accHwrWEzF40e2mkfK960/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bhKxYw/btsNqqcPAp0/0accHwrWEzF40e2mkfK960/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bhKxYw/btsNqqcPAp0/0accHwrWEzF40e2mkfK960/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbhKxYw%2FbtsNqqcPAp0%2F0accHwrWEzF40e2mkfK960%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;2000&quot; height=&quot;1125&quot; data-filename=&quot;슬라이드51.PNG&quot; data-origin-width=&quot;2000&quot; data-origin-height=&quot;1125&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div data-message-model-slug=&quot;gpt-4o-mini&quot; data-message-id=&quot;163f5a61-fb6b-47c2-896d-95368c495e04&quot; data-message-author-role=&quot;assistant&quot;&gt;
&lt;div&gt;
&lt;div&gt;
&lt;p data-end=&quot;245&quot; data-start=&quot;0&quot; data-ke-size=&quot;size16&quot;&gt;Top-down DP에서는 재귀적으로 구현이 이루어지며 이는 밑에서부터 값을 채워가는 것이 아니라 반대로 위에서부터 시작해 필요한 값을 계산하기 위해 재귀적으로 호출하는 구조입니다. 예를 들어, fibo(5)를 호출하면 fibo(5)를 계산하기 위해 fibo(4)와 fibo(3)의 값이 필요하므로 이들 역시 호출하게 됩니다. 값이 채워지는 과정은 여전히 동일하지만 호출하는 과정에서의 흐름은 bottom-up과 반대가 됩니다.&lt;/p&gt;
&lt;p data-end=&quot;245&quot; data-start=&quot;0&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;574&quot; data-start=&quot;247&quot; data-ke-size=&quot;size16&quot;&gt;Top-down DP에서 중요한 점은 4번과 5번 줄에서의 연산입니다. 피보나치 수열을 그냥 재귀로 구현하면 시간 복잡도가 지수적으로 증가하는 이유는 중복 계산이 계속 발생하기 때문입니다. 이를 해결하기 위해서는 이미 계산한 값에 대해 다시 재귀 호출을 하지 않도록 해야 합니다. 예를 들어, f의 초기값을 -1로 설정한 후 fibo(n)을 호출하면 f[n]이 -1이 아니라면 그 값이 이미 계산되어 있음을 의미하고, 이때는 다시 계산할 필요 없이 바로 f[n]을 반환하면 됩니다. 이러한 기법을 메모이제이션이라고 하며, 메모이제이션을 사용하면 중복 계산을 방지할 수 있습니다.&lt;/p&gt;
&lt;p data-end=&quot;574&quot; data-start=&quot;247&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;787&quot; data-start=&quot;576&quot; data-ke-size=&quot;size16&quot;&gt;이와 같은 방식으로 코드를 구성하면 먼저 f[n]을 확인해 계산된 적이 있는지 확인하고, 그다음 초기값 조건을 걸러낸 후 마지막으로 점화식에 따라 f[n]을 계산하는 방식으로 진행됩니다.&lt;/p&gt;
&lt;p data-end=&quot;787&quot; data-start=&quot;576&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;955&quot; data-start=&quot;789&quot; data-ke-size=&quot;size16&quot;&gt;초기값을 설정할 때 f 테이블에 처음 넣는 값은 실제 값이 될 수 없는 값으로 설정해야 합니다. 예를 들어 값들이 모두 양수라면 -1을 넣고, 만약 음수 값이 나올 수 있다면 가능한 최솟값보다 1 작은 값을 넣는 등의 처리가 필요할 수 있습니다. 이런 처리를 적절하게 하는건 지금까지의 알고리즘 짬밥이라면 충분히 해낼 수 있다고 생각합니다.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;슬라이드52.PNG&quot; data-origin-width=&quot;2000&quot; data-origin-height=&quot;1125&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cockOB/btsNr6ECgoo/SklXqipif354CqvGeKpBuk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cockOB/btsNr6ECgoo/SklXqipif354CqvGeKpBuk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cockOB/btsNr6ECgoo/SklXqipif354CqvGeKpBuk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcockOB%2FbtsNr6ECgoo%2FSklXqipif354CqvGeKpBuk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;2000&quot; height=&quot;1125&quot; data-filename=&quot;슬라이드52.PNG&quot; data-origin-width=&quot;2000&quot; data-origin-height=&quot;1125&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;239&quot; data-start=&quot;0&quot; data-ke-size=&quot;size16&quot;&gt;당연히 같은 식과 테이블을 사용해 DP를 푼다면, bottom-up 방식이든 top-down 방식이든 시간 복잡도는 동일합니다. 예를 들어, 8번째 줄에서처럼 값을 구하는 과정은 각 테이블의 칸에 대해 한 번씩만 이루어집니다. bottom-up에서는 테이블을 차례대로 채워가며 값을 계산하고, top-down에서는 한 번 값이 들어가면 그 후에는 재귀 호출이 발생해도 이미 계산된 값이 반환되기 때문에 다시 계산하지 않습니다.&lt;/p&gt;
&lt;p data-end=&quot;239&quot; data-start=&quot;0&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;306&quot; data-start=&quot;241&quot; data-ke-size=&quot;size16&quot;&gt;따라서 시간 복잡도는 두 방식 모두 동일하고 기본적으로 그냥 둘의 차이는 구현 방식의 차이인건데, 각 방식의 장단점을 살펴보겠습니다.&lt;/p&gt;
&lt;p data-end=&quot;306&quot; data-start=&quot;241&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;슬라이드53.PNG&quot; data-origin-width=&quot;2000&quot; data-origin-height=&quot;1125&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/ph27j/btsNsbGKneF/0xHUqFiXVKgp54WKL6amuK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/ph27j/btsNsbGKneF/0xHUqFiXVKgp54WKL6amuK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/ph27j/btsNsbGKneF/0xHUqFiXVKgp54WKL6amuK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fph27j%2FbtsNsbGKneF%2F0xHUqFiXVKgp54WKL6amuK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;2000&quot; height=&quot;1125&quot; data-filename=&quot;슬라이드53.PNG&quot; data-origin-width=&quot;2000&quot; data-origin-height=&quot;1125&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;252&quot; data-start=&quot;0&quot; data-ke-size=&quot;size16&quot;&gt;먼저 시간 복잡도는 이전에 설명한 것처럼 두 방식이 동일하지만 실제 실행 시간에서는 bottom-up 방식이 더 빠릅니다. 왜냐하면 bottom-up은 단순히 반복문을 통해 테이블을 차례대로 채워가기 때문에 함수 호출이 없어 효율적입니다. 반면, top-down 방식은 재귀 호출을 사용하기 때문에 반복문보다 무거운 함수 호출 연산이 발생하게 됩니다. 하지만 top-down 방식이 느리다고 해서 시간 초과가 발생할 정도로 문제가 생기지는 않기 때문에 저는 꼭 top-down을 사용해야 하는 상황이 아니라면 bottom-up 방식으로 문제를 푸는 것을 더 선호하긴 하지만 개인적인 취향에 따라 top-down을 써도 크게 문제가 되지 않습니다.&lt;/p&gt;
&lt;p data-end=&quot;599&quot; data-start=&quot;468&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;599&quot; data-start=&quot;468&quot; data-ke-size=&quot;size16&quot;&gt;그리고 top-down 방식이 효과적인 상황은 테이블을 일부만 채워야 하거나 테이블을 채우는 순서가 복잡할 때입니다. 이러한 경우에는 top-down 방식이 더 유용할 수 있고 각각이 어떤 상황인지는 직접 문제를 풀면서 확인해보겠습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;슬라이드54.PNG&quot; data-origin-width=&quot;2000&quot; data-origin-height=&quot;1125&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dMmj74/btsNsh7LIao/dlIKK5vpcEimKxqtP7AEp0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dMmj74/btsNsh7LIao/dlIKK5vpcEimKxqtP7AEp0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dMmj74/btsNsh7LIao/dlIKK5vpcEimKxqtP7AEp0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdMmj74%2FbtsNsh7LIao%2FdlIKK5vpcEimKxqtP7AEp0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;2000&quot; height=&quot;1125&quot; data-filename=&quot;슬라이드54.PNG&quot; data-origin-width=&quot;2000&quot; data-origin-height=&quot;1125&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://www.acmicpc.net/problem/1351&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;BOJ 1351번: 무한 수열&lt;/a&gt; 문제를 살펴보면 테이블과 초기값, 그리고 점화식까지 모두 제공된 것을 확인할 수 있습니다. 하지만 이 문제를 bottom-up 방식으로 해결하기는 어렵습니다. A[0], A[1]처럼 순차적으로 값을 채워나가기에는 N의 크기가 무려 10^12이기 때문입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;슬라이드55.PNG&quot; data-origin-width=&quot;2000&quot; data-origin-height=&quot;1125&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bLKwxS/btsNrW36XuS/SiL3nrb7KqGefk0mE0cJPK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bLKwxS/btsNrW36XuS/SiL3nrb7KqGefk0mE0cJPK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bLKwxS/btsNrW36XuS/SiL3nrb7KqGefk0mE0cJPK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbLKwxS%2FbtsNrW36XuS%2FSiL3nrb7KqGefk0mE0cJPK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;2000&quot; height=&quot;1125&quot; data-filename=&quot;슬라이드55.PNG&quot; data-origin-width=&quot;2000&quot; data-origin-height=&quot;1125&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그런데 A[0]부터 A[N]까지 모든 값을 실제로 계산할 필요는 없습니다. 예제 1에서 주어진 N, P, Q 값을 기준으로 A[N]을 구하는 데 필요한 값들만 따로 추려 그래프로 나타내보면, A[4], A[5], A[6]과 같은 값들은 굳이 계산하지 않아도 된다는 것을 확인할 수 있습니다. 또한 주어진 N에 대해 top-down 방식으로 계산을 진행하면 필요한 값들만 재귀적으로 호출하면서 계산이 이루어지게 됩니다. 그리고 공간을 절약하기 위해 A를 배열로 선언하는 대신 맵을 사용하는 것이 효과적입니다. 이제&amp;nbsp;바로&amp;nbsp;구현을&amp;nbsp;진행해보겠습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;슬라이드56.PNG&quot; data-origin-width=&quot;2000&quot; data-origin-height=&quot;1125&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/w30uN/btsNsh00sDb/8Z084dTx3ckxMxVTJJ4TAK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/w30uN/btsNsh00sDb/8Z084dTx3ckxMxVTJJ4TAK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/w30uN/btsNsh00sDb/8Z084dTx3ckxMxVTJJ4TAK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fw30uN%2FbtsNsh00sDb%2F8Z084dTx3ckxMxVTJJ4TAK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;2000&quot; height=&quot;1125&quot; data-filename=&quot;슬라이드56.PNG&quot; data-origin-width=&quot;2000&quot; data-origin-height=&quot;1125&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;구현 자체는 매우 간단합니다. 테이블과 점화식을 정한 뒤 재귀적으로 함수를 작성하면 A[N]을 구하기 위해 필요한 값들을 따라가며 계산이 이루어집니다. 결국 재귀 호출을 거치다 보면 초기값인 go(0)에 도달하게 되고 이 값이 재귀의 기본 조건, 즉 base condition 역할을 해서 결과를 올바르게 도출할 수 있습니다. 이처럼 테이블의 모든 값을 채우는 것이 아니라 일부 값만 필요할 경우에는 top-down 방식을 사용하면 자연스럽게 필요한 값만 계산하게 됩니다.&lt;br /&gt;&lt;br /&gt;또한 구현의 디테일을 또 한 하나 짚어보자면, map a에서 이전에 키 k가 존재하지 않았을 때 a[k]를 호출하면 기본값으로 0이 설정된다는 특성을 이용해서 아홉 번째 줄에서는 a[k]가 0이 아닌 경우 이미 해당 값이 계산된 것으로 판단하고 처리를 진행하였습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/EXeLQ/btsNtPxk8xF/qVLdTIjNDct2QpSfaHHC9k/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/EXeLQ/btsNtPxk8xF/qVLdTIjNDct2QpSfaHHC9k/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/EXeLQ/btsNtPxk8xF/qVLdTIjNDct2QpSfaHHC9k/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FEXeLQ%2FbtsNtPxk8xF%2FqVLdTIjNDct2QpSfaHHC9k%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1920&quot; height=&quot;1080&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;두 번째로 확인해볼 부분은, 테이블을 채우는 순서가 복잡한 경우에 대한 예시입니다. &lt;a href=&quot;https://www.acmicpc.net/problem/1937&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;BOJ 1937번: 욕심쟁이 판다&lt;/a&gt; 문제를 살펴보면, 테이블의 정의나 점화식 자체는 비교적 쉽게 유추할 수 있습니다. D[i][j]를 (i, j) 칸에서 출발했을 때 이동할 수 있는 칸의 수라고 정의하면 단순히 상하좌우를 확인하면서 대나무 양이 더 많은 방향으로 이동한다고 생각하면 되니 &lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;점화식도&lt;span&gt; &lt;/span&gt;&lt;/span&gt;그 방향의 D 값에 1을 더해주는 방식으로 쉽게 구성할 수 있습니다.&lt;br /&gt;&lt;br /&gt;하지만 여기서 중요한 점은, 테이블을 어떤 순서로 채워야 하는가입니다. 지금까지는 대부분 2중 반복문을 사용하여 D[0][0]부터 순서대로 값을 채워나가면 문제가 없었습니다. 그러나 이 문제에서는 상황이 다릅니다. 문제에서 제시된 예제만 보더라도, D[0][1]의 값을 구하려면 D[0][0], D[0][2], D[1][1]이 이미 계산되어 있어야 합니다. 이처럼 특정 위치의 값을 구하기 위해서는 그보다 앞서 다른 위치들이 먼저 계산되어야 하므로, 테이블을 채우는 순서가 복잡해집니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;슬라이드58.PNG&quot; data-origin-width=&quot;2000&quot; data-origin-height=&quot;1125&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bRI3ok/btsNotO9cUq/HAl0xNia5O2lwLAVKK7pjk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bRI3ok/btsNotO9cUq/HAl0xNia5O2lwLAVKK7pjk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bRI3ok/btsNotO9cUq/HAl0xNia5O2lwLAVKK7pjk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbRI3ok%2FbtsNotO9cUq%2FHAl0xNia5O2lwLAVKK7pjk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;2000&quot; height=&quot;1125&quot; data-filename=&quot;슬라이드58.PNG&quot; data-origin-width=&quot;2000&quot; data-origin-height=&quot;1125&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이러한 상황에서 테이블을 어떤 순서로 채워야 할지를 파악하기 위해 D[a][b]를 구할 때 D[c][d]의 값이 필요하다면, (c, d)에서 (a, b)로 향하는 간선을 그어 그래프를 구성해보았습니다. 예를 들어 D[0][1]을 계산하기 위해 D[0][0]이 필요하다면, (0, 0)에서 (0, 1)로 가는 간선을 하나 추가하는 식입니다. 그런데 이렇게 봐도 눈에 잘 안들어오는건 매한가지입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;슬라이드59.PNG&quot; data-origin-width=&quot;2000&quot; data-origin-height=&quot;1125&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bZVNqE/btsNrxp03Vy/NCwQhzSlOlMhVG8kSNICek/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bZVNqE/btsNrxp03Vy/NCwQhzSlOlMhVG8kSNICek/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bZVNqE/btsNrxp03Vy/NCwQhzSlOlMhVG8kSNICek/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbZVNqE%2FbtsNrxp03Vy%2FNCwQhzSlOlMhVG8kSNICek%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;2000&quot; height=&quot;1125&quot; data-filename=&quot;슬라이드59.PNG&quot; data-origin-width=&quot;2000&quot; data-origin-height=&quot;1125&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그래서 조금 더 알아보기 쉽게 그래프 상에서 각 위치를 조정해보았습니다. 물론 이 방식도 완전히 만족스럽지는 않지만 현 시점에서는 이 정도가 최선인 것 같습니다. 이때 이 문제를 동적 계획법으로 해결하려면 해당 그래프에 사이클이 없어야 하는데, 다행히 간선이 항상 값이 더 큰 정점에서 더 작은 정점으로만 연결되기 때문에 사이클이 생길 가능성은 없습니다.&lt;br /&gt;&lt;br /&gt;그리고 14, 15, 12, 16, 13과 같은 정점들은 indegree가 0입니다. 이는 인접한 칸 중 자신보다 대나무의 양이 많은 칸이 없다는 뜻이므로 해당 위치의 D 값은 곧바로 1로 정해질 수 있습니다. 이런 값들이 초기값이 되고 이후 그래프에서 위상 정렬된 순서대로 동적 계획을 진행해나가면 문제를 해결할 수 있습니다. 이것이 bottom-up 방식의 접근입니다.&lt;br /&gt;&lt;br /&gt;만약 구현을 더 간단하게 하고 싶다면 각 칸을 대나무의 양을 기준으로 정렬한 후 내림차순으로 테이블을 채워나가는 방식도 사용할 수 있습니다. 앞서 설명했듯이 간선은 반드시 값이 더 큰 정점에서 더 작은 정점으로 연결되기 때문에, 대나무가 많은 칸부터 차례로 값을 계산해도 올바른 결과를 얻을 수 있습니다.&lt;br /&gt;&lt;br /&gt;이처럼 문제는 해결 가능하지만 어쨌든 테이블을 채우는 순서가 단순하지 않다는 점은 여전히 남아 있습니다. 어느 정도 고민을 통해 적절히 순서를 정해줘야 하고, 위상 정렬 방식은 구현이 다소 복잡한 반면 정렬을 사용하는 방식은 구현은 간단하지만 시간 복잡도에 불필요한 log N이 추가된다는 단점이 있습니다.&lt;br /&gt;&lt;br /&gt;이제 이 문제를 top-down 방식으로 접근하면 어떻게 될지 살펴보겠습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;슬라이드60.PNG&quot; data-origin-width=&quot;2000&quot; data-origin-height=&quot;1125&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/ck7aZq/btsNrZ0VbeY/HiiWIPYOB4CtffxtmYJye0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/ck7aZq/btsNrZ0VbeY/HiiWIPYOB4CtffxtmYJye0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/ck7aZq/btsNrZ0VbeY/HiiWIPYOB4CtffxtmYJye0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fck7aZq%2FbtsNrZ0VbeY%2FHiiWIPYOB4CtffxtmYJye0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;2000&quot; height=&quot;1125&quot; data-filename=&quot;슬라이드60.PNG&quot; data-origin-width=&quot;2000&quot; data-origin-height=&quot;1125&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;top-down 방식에서는 재귀적인 형태로 코드를 작성해두고, 어떤 값을 호출하면 그에 필요한 값들을 자동으로 호출하면서 base condition까지 내려가게 됩니다. 여기서 정말 흥미로운 점은, 호출 순서에 대해 전혀 신경 쓸 필요가 없다는 사실입니다.&lt;br /&gt;&lt;br /&gt;이게 무슨 의미인지 함께 살펴보겠습니다. 앞서 top-down 방식으로 문제를 구현했을 때의 흐름대로 코드가 구현되어 있다고 생각하고 보면 되는데, 만약 아직 그 감이 잘 잡히지 않는다면 언제나처럼 이 문제에 대한 코드를 제가 뒤쪽에 작성해두었으니 그것을 함께 보면서 설명을 이해해보셔도 좋습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;슬라이드61.PNG&quot; data-origin-width=&quot;2000&quot; data-origin-height=&quot;1125&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cG3jIx/btsNr0eoYOg/OwHlBuK4FIWW51VO7VfSE0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cG3jIx/btsNr0eoYOg/OwHlBuK4FIWW51VO7VfSE0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cG3jIx/btsNr0eoYOg/OwHlBuK4FIWW51VO7VfSE0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcG3jIx%2FbtsNr0eoYOg%2FOwHlBuK4FIWW51VO7VfSE0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;2000&quot; height=&quot;1125&quot; data-filename=&quot;슬라이드61.PNG&quot; data-origin-width=&quot;2000&quot; data-origin-height=&quot;1125&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;go(i, j) 함수가 D[i][j] 값을 구하는 함수라고 하고, 그냥 편하게 우리가 익숙한 순서대로 go(0, 0), go(0, 1)처럼 순서대로 호출한다고 가정해보겠습니다. 먼저 go(0, 0)을 호출하면, 대나무 양이 14인 칸의 D 값을 구하려는 상황이 됩니다. 그래프로도 확인할 수 있듯이 D[0][0]을 계산하기 위해 미리 구해져 있어야 할 값이 따로 없습니다. 따라서 이 경우 D[0][0]은 1이라는 사실을 바로 알 수 있습니다. 이렇게 계산이 완료된 정점은 시각적으로 구분하기 위해 주황색으로 표시하겠습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;슬라이드62.PNG&quot; data-origin-width=&quot;2000&quot; data-origin-height=&quot;1125&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/Ziop1/btsNsTkPRkJ/9YxF9OZX5C7m1kdyMDWo51/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/Ziop1/btsNsTkPRkJ/9YxF9OZX5C7m1kdyMDWo51/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/Ziop1/btsNsTkPRkJ/9YxF9OZX5C7m1kdyMDWo51/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FZiop1%2FbtsNsTkPRkJ%2F9YxF9OZX5C7m1kdyMDWo51%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;2000&quot; height=&quot;1125&quot; data-filename=&quot;슬라이드62.PNG&quot; data-origin-width=&quot;2000&quot; data-origin-height=&quot;1125&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다음으로 go(0, 1)을 호출하면, 대나무 양이 9인 정점에 해당하게 됩니다. 이 값을 구하려면 D[0][0], D[0][2], D[1][1]의 값이 모두 필요합니다. 그러면 구조적으로 자연스럽게 go(0, 0), go(0, 2), go(1, 1) 세 함수가 모두 호출됩니다.&lt;br /&gt;&lt;br /&gt;이 중 go(0, 0)은 이미 D[0][0]이 계산되어 있기 때문에 해당 값을 그대로 반환하게 됩니다. 그리고 go(0, 2)의 경우에도 D[0][2]가 1이므로 바로 계산이 끝납니다. go(1, 1)을 호출하면, 이 함수는 내부에서 다시 go(1, 2)를 호출하게 됩니다.&lt;br /&gt;&lt;br /&gt;이러한&amp;nbsp;호출&amp;nbsp;과정을&amp;nbsp;계속&amp;nbsp;따라가다&amp;nbsp;보면,&amp;nbsp;결국&amp;nbsp;9인&amp;nbsp;정점에&amp;nbsp;도달할&amp;nbsp;수&amp;nbsp;있는&amp;nbsp;모든&amp;nbsp;경로에&amp;nbsp;있는&amp;nbsp;정점들의&amp;nbsp;값이&amp;nbsp;전부&amp;nbsp;계산되게&amp;nbsp;됩니다.&amp;nbsp;함수&amp;nbsp;호출&amp;nbsp;도중&amp;nbsp;그&amp;nbsp;칸들을&amp;nbsp;자동으로&amp;nbsp;호출하면서&amp;nbsp;D&amp;nbsp;값을&amp;nbsp;하나씩&amp;nbsp;채워나가기&amp;nbsp;때문입니다.&lt;br /&gt;&lt;br /&gt;결과적으로&amp;nbsp;이미&amp;nbsp;계산되어&amp;nbsp;있던&amp;nbsp;14에&amp;nbsp;더해,&amp;nbsp;9,&amp;nbsp;11,&amp;nbsp;15,&amp;nbsp;12의&amp;nbsp;값이&amp;nbsp;새롭게&amp;nbsp;계산되어&amp;nbsp;저장됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;슬라이드63.PNG&quot; data-origin-width=&quot;2000&quot; data-origin-height=&quot;1125&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cblJWY/btsNsORAzXc/6nWqZiL5Smh3ybExl5YCo1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cblJWY/btsNsORAzXc/6nWqZiL5Smh3ybExl5YCo1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cblJWY/btsNsORAzXc/6nWqZiL5Smh3ybExl5YCo1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcblJWY%2FbtsNsORAzXc%2F6nWqZiL5Smh3ybExl5YCo1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;2000&quot; height=&quot;1125&quot; data-filename=&quot;슬라이드63.PNG&quot; data-origin-width=&quot;2000&quot; data-origin-height=&quot;1125&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-pm-slice=&quot;0 0 []&quot; data-ke-size=&quot;size16&quot;&gt;다음으로 go(0, 2)는 이미 값이 있으니 별 일이 안생기고&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;슬라이드64.PNG&quot; data-origin-width=&quot;2000&quot; data-origin-height=&quot;1125&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bcR2Nv/btsNslvB6Hr/Ki9fshiR7BEqfHPbfX7s0k/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bcR2Nv/btsNslvB6Hr/Ki9fshiR7BEqfHPbfX7s0k/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bcR2Nv/btsNslvB6Hr/Ki9fshiR7BEqfHPbfX7s0k/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbcR2Nv%2FbtsNslvB6Hr%2FKi9fshiR7BEqfHPbfX7s0k%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;2000&quot; height=&quot;1125&quot; data-filename=&quot;슬라이드64.PNG&quot; data-origin-width=&quot;2000&quot; data-origin-height=&quot;1125&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;go(0, 3)은 10인 정점을 계산할 때 12가 필요한데 이미 계산되어 있으니&amp;nbsp;자연스럽게 또 D[0][3]을 구할 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;슬라이드65.PNG&quot; data-origin-width=&quot;2000&quot; data-origin-height=&quot;1125&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/RVzZG/btsNsb7Q1rK/FKvOPTN5GD6dYmfrwnA1T1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/RVzZG/btsNsb7Q1rK/FKvOPTN5GD6dYmfrwnA1T1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/RVzZG/btsNsb7Q1rK/FKvOPTN5GD6dYmfrwnA1T1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FRVzZG%2FbtsNsb7Q1rK%2FFKvOPTN5GD6dYmfrwnA1T1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;2000&quot; height=&quot;1125&quot; data-filename=&quot;슬라이드65.PNG&quot; data-origin-width=&quot;2000&quot; data-origin-height=&quot;1125&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다음은 go(1, 0)을 호출하는 경우입니다. 이 함수가 D[1][0]을 계산하려면 D[0][0], D[1][1], D[2][0]의 값이 필요합니다. 그런데 D[0][0]과 D[1][1]은 이미 앞서 계산이 완료된 상태이므로 go(0, 0)과 go(1, 1)은 더 이상 깊이 들어가지 않고 바로 해당 값을 반환하게 됩니다.&lt;br /&gt;&lt;br /&gt;이제 남은 go(2, 0)을 호출하면, 이 함수는 다시 D[2][1] 값을 활용해서 D[2][0]을 계산하게 됩니다. 이 흐름대로 계산이 진행되면 결국 새롭게 1과 7에 해당하는 칸의 값이 채워지게 됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;슬라이드66.PNG&quot; data-origin-width=&quot;2000&quot; data-origin-height=&quot;1125&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bqTvI9/btsNsNE8Gsz/0Klk1Z6xkS0l37Hw1AfzR1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bqTvI9/btsNsNE8Gsz/0Klk1Z6xkS0l37Hw1AfzR1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bqTvI9/btsNsNE8Gsz/0Klk1Z6xkS0l37Hw1AfzR1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbqTvI9%2FbtsNsNE8Gsz%2F0Klk1Z6xkS0l37Hw1AfzR1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;2000&quot; height=&quot;1125&quot; data-filename=&quot;슬라이드66.PNG&quot; data-origin-width=&quot;2000&quot; data-origin-height=&quot;1125&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 정도 보여드렸다면 대충 눈치를 챘을 것이라고 생각합니다. 특정 정점을 호출하면 해당 정점을 조상으로 두는 아래 정점들의 값도 자연스럽게 구해집니다. 그리고 top-down에서 가장 중요한 메모이제이션 덕분에 이미 값을 구한 정점에 대해 다시 계산하는 일은 절대 발생하지 않습니다. 그래서 DP 테이블을 채우고 싶은 입장에서는 이 그래프가 어떻게 생겼는지 전혀 신경 쓸 필요 없이 go(0, 0)부터 go(3, 3)까지 모두 한 번씩 호출만 해주면 테이블이 자동으로 채워집니다.&lt;br /&gt;&lt;br /&gt;다시 한 번 강조하지만 각 칸에서 상하좌우 칸을 살펴보고 최대값을 구하는 등의 DP 식을 계산하는 과정은 단 한 번만 발생하므로 시간 복잡도는 O(N^2)입니다. 아마 시간 복잡도에서 혼동이 있을 수 있는데, &lt;a href=&quot;https://www.acmicpc.net/problem/1926&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;BOJ 1926번: 그림&lt;/a&gt; 문제에서 2중 for문을 돌면서 방문 표시를 남기고 현재 방문하지 않은 점을 모두 BFS의 시작점으로 삼는 방식도 전체 시간 복잡도는 O(NM)였던 것과 상황이 똑같습니다.&lt;br /&gt;&lt;br /&gt;즉,&amp;nbsp;BFS에서는&amp;nbsp;방문&amp;nbsp;표시를&amp;nbsp;통해,&amp;nbsp;DP에서는&amp;nbsp;메모이제이션을&amp;nbsp;통해&amp;nbsp;중복&amp;nbsp;계산을&amp;nbsp;막아서&amp;nbsp;각&amp;nbsp;칸마다&amp;nbsp;DP&amp;nbsp;식을&amp;nbsp;한&amp;nbsp;번만&amp;nbsp;계산하는&amp;nbsp;구조입니다.&amp;nbsp;이&amp;nbsp;점을&amp;nbsp;이해하시면&amp;nbsp;됩니다.&amp;nbsp;이제&amp;nbsp;바로&amp;nbsp;구현을&amp;nbsp;시작하겠습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/CqHcC/btsNuw4wEml/gpQJkg24lcYU4AIbkjaXf0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/CqHcC/btsNuw4wEml/gpQJkg24lcYU4AIbkjaXf0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/CqHcC/btsNuw4wEml/gpQJkg24lcYU4AIbkjaXf0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FCqHcC%2FbtsNuw4wEml%2FgpQJkg24lcYU4AIbkjaXf0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1920&quot; height=&quot;1080&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;애매하게 길어서 한 장에 다 담기 어려운 부분이 있겠지만, 일단 go 함수까지만 보면 특별히 설명이 필요한 부분은 없습니다. 그냥 말한 그대로입니다. &lt;a href=&quot;https://github.com/encrypted-def/basic-algo-lecture/blob/master/Appendix%20E/1937.cpp&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;(코드)&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;슬라이드68.PNG&quot; data-origin-width=&quot;2000&quot; data-origin-height=&quot;1125&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/nTXo2/btsNrz2tE8V/zviHksOL7pS6oFnV7fCJU0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/nTXo2/btsNrz2tE8V/zviHksOL7pS6oFnV7fCJU0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/nTXo2/btsNrz2tE8V/zviHksOL7pS6oFnV7fCJU0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FnTXo2%2FbtsNrz2tE8V%2FzviHksOL7pS6oFnV7fCJU0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;2000&quot; height=&quot;1125&quot; data-filename=&quot;슬라이드68.PNG&quot; data-origin-width=&quot;2000&quot; data-origin-height=&quot;1125&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그리고 main 함수도 그냥 자연스럽게 go를 go(0, 0)부터 go(n-1, n-1)까지 한 번씩 다 호출하고 max를 구하면 그게 답입니다. 이렇게 채우는 순서가 복잡할 때는 top-down을 이용하면 순서를 내가 신경 쓸 필요 없이 재귀적으로 알아서 해결되는 예시를 살펴봤습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;슬라이드69.PNG&quot; data-origin-width=&quot;2000&quot; data-origin-height=&quot;1125&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bVqy0T/btsNrz2tE4j/XLcP96isKWKMO5Auh6Bcfk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bVqy0T/btsNrz2tE4j/XLcP96isKWKMO5Auh6Bcfk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bVqy0T/btsNrz2tE4j/XLcP96isKWKMO5Auh6Bcfk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbVqy0T%2FbtsNrz2tE4j%2FXLcP96isKWKMO5Auh6Bcfk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;2000&quot; height=&quot;1125&quot; data-filename=&quot;슬라이드69.PNG&quot; data-origin-width=&quot;2000&quot; data-origin-height=&quot;1125&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이제&amp;nbsp;남은&amp;nbsp;것은&amp;nbsp;트리&amp;nbsp;DP와&amp;nbsp;위상&amp;nbsp;정렬&amp;nbsp;DP인데,&amp;nbsp;미리&amp;nbsp;살짝&amp;nbsp;스포를&amp;nbsp;하자면&amp;nbsp;트리나&amp;nbsp;위상&amp;nbsp;정렬이나&amp;nbsp;그것을&amp;nbsp;그래프로&amp;nbsp;표현하면&amp;nbsp;DAG(Directed&amp;nbsp;Acyclic&amp;nbsp;Graph)가&amp;nbsp;되기&amp;nbsp;때문에&amp;nbsp;자연스럽게&amp;nbsp;그&amp;nbsp;안에서&amp;nbsp;DP가&amp;nbsp;잘&amp;nbsp;정의됩니다.&amp;nbsp;그래서&amp;nbsp;개념&amp;nbsp;자체는&amp;nbsp;그렇게&amp;nbsp;어렵지&amp;nbsp;않습니다.&amp;nbsp;물론&amp;nbsp;이를&amp;nbsp;응용할&amp;nbsp;여지는&amp;nbsp;무궁무진하지만,&amp;nbsp;이번&amp;nbsp;강의에서는&amp;nbsp;트리&amp;nbsp;DP&amp;nbsp;혹은&amp;nbsp;위상&amp;nbsp;정렬&amp;nbsp;DP가&amp;nbsp;어떤&amp;nbsp;것인지&amp;nbsp;알&amp;nbsp;수&amp;nbsp;있도록&amp;nbsp;대표적인&amp;nbsp;문제&amp;nbsp;한&amp;nbsp;가지를&amp;nbsp;다룰&amp;nbsp;예정입니다.&lt;br /&gt;&lt;br /&gt;먼저 트리 DP부터 보면, 트리 단원에서는 트리 DP를 깊게 다루지 않았습니다. 그러나 문제집의 응용 문제에는 몇 가지를 포함시켰습니다. 기본적으로 트리 DP는 트리에서 DP를 하는 문제입니다. 트리 DP의 느낌을 잡아보려면 주어진 트리에서 각 정점에 가중치가 있고, 이 정점이 속한 서브트리에서 가중치 합이 최대인 서브트리를 찾는 문제를 생각해볼 수 있습니다.&lt;br /&gt;&lt;br /&gt;이&amp;nbsp;예시에서는&amp;nbsp;3이&amp;nbsp;루트인&amp;nbsp;트리가&amp;nbsp;가중치&amp;nbsp;합이&amp;nbsp;3+4=7로&amp;nbsp;최대입니다.&amp;nbsp;그럼&amp;nbsp;모든&amp;nbsp;정점에&amp;nbsp;대해&amp;nbsp;자기&amp;nbsp;자신과&amp;nbsp;자기&amp;nbsp;자식들의&amp;nbsp;가중치&amp;nbsp;합을&amp;nbsp;구해서&amp;nbsp;그&amp;nbsp;중&amp;nbsp;최대를&amp;nbsp;찾으면&amp;nbsp;되겠지만,&amp;nbsp;이렇게&amp;nbsp;구현하면&amp;nbsp;시간&amp;nbsp;복잡도가&amp;nbsp;얼마나&amp;nbsp;될까요?&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;슬라이드70.PNG&quot; data-origin-width=&quot;2000&quot; data-origin-height=&quot;1125&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cuGBH2/btsNsSzrOHo/CZoLkzeC0dpfcFda8e6Kw1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cuGBH2/btsNsSzrOHo/CZoLkzeC0dpfcFda8e6Kw1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cuGBH2/btsNsSzrOHo/CZoLkzeC0dpfcFda8e6Kw1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcuGBH2%2FbtsNsSzrOHo%2FCZoLkzeC0dpfcFda8e6Kw1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;2000&quot; height=&quot;1125&quot; data-filename=&quot;슬라이드70.PNG&quot; data-origin-width=&quot;2000&quot; data-origin-height=&quot;1125&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;만약 진짜 정직하게 각 노드마다 거기서 BFS나 DFS를 시작해서 그 노드를 루트로 하는 서브트리를 다 순회하는 전략을 취한다면, 정점이 N개일 때 시간 복잡도는 O(N^2)가 될 것입니다. 왜냐하면 각 정점마다 최대 N번 순회를 해야 하기 때문입니다. 그런데 지금 이 방법은 최적화할 여지가 너무 뻔하게 보입니다. 예를 들어, 루트가 2인 서브트리를 순회해서 (2, -9, 5)의 합이 -2라는 걸 이미 알았다면 루트가 0인 서브트리를 계산할 때 굳이 (2, -9, 5)를 다시 순회할 필요는 없습니다. 그냥 바로 -2라는 값만 가져오면 되기 때문입니다.&lt;br /&gt;&lt;br /&gt;D[i]를 가중치가 i인 정점에 대해 서브트리의 가중치의 합이라고 한다면, D[1]을 구하기 위해 모든 정점을 다 보는 게 아니라, D[1] = 1 + D[3] + D[-7] + D[0] 이런 방식으로 계산할 수 있습니다. 이렇게 하면 각 D 값을 구할 때 자기 자식들의 D 값만 가져오면 되고, 다른 관점에서 보면 각 D 값은 자신의 부모에게만 딱 한 번 더해지니까 전체적으로 시간 복잡도는 O(N)이 됩니다. 이처럼 트리에서 메모이제이션을 활용하면 시간 복잡도를 줄일 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;슬라이드71.PNG&quot; data-origin-width=&quot;2000&quot; data-origin-height=&quot;1125&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/R9v1J/btsNsqcmHg1/xxl3GP5Kc3jJQE2TLKWHD1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/R9v1J/btsNsqcmHg1/xxl3GP5Kc3jJQE2TLKWHD1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/R9v1J/btsNsqcmHg1/xxl3GP5Kc3jJQE2TLKWHD1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FR9v1J%2FbtsNsqcmHg1%2Fxxl3GP5Kc3jJQE2TLKWHD1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;2000&quot; height=&quot;1125&quot; data-filename=&quot;슬라이드71.PNG&quot; data-origin-width=&quot;2000&quot; data-origin-height=&quot;1125&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이렇게&amp;nbsp;트리&amp;nbsp;DP의&amp;nbsp;느낌은&amp;nbsp;대충&amp;nbsp;잡았으니&amp;nbsp;문제를&amp;nbsp;하나&amp;nbsp;풀어보겠습니다.&amp;nbsp;너무&amp;nbsp;뻔한&amp;nbsp;것&amp;nbsp;말고&amp;nbsp;적당히&amp;nbsp;어려워서&amp;nbsp;&quot;아,&amp;nbsp;이게&amp;nbsp;트리&amp;nbsp;DP구나&quot;&amp;nbsp;하고&amp;nbsp;음미할&amp;nbsp;수&amp;nbsp;있는&amp;nbsp;수준의&amp;nbsp;문제를&amp;nbsp;준비했습니다.&lt;br /&gt;&lt;br /&gt;일단 &lt;a href=&quot;https://www.acmicpc.net/problem/1949&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;BOJ 1949번: 우수 마을&lt;/a&gt; 문제를 보면 어렵습니다. 어려운 것은 맞지만 아예 밑도 끝도 없이 새로운 것은 아닙니다. &lt;a href=&quot;https://www.acmicpc.net/problem/1149&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;BOJ 1149번: RGB거리&lt;/a&gt;나 &lt;a href=&quot;https://www.acmicpc.net/problem/9465&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;BOJ 9465번: 스티커&lt;/a&gt; 문제를 한 번 다시 보고 오시면, 일단 트리는 배제하고 마을이 만약 일자로 생겨 있다고 했을 때 대충 맥락은 알 수 있을 것입니다. 차례차례 구해나가면서 각 정점이 우수 마을일 때와 아닐 때의 주민 수의 총합 중 최대를 계속 관리해 나가면 될 것 같습니다.&lt;br /&gt;&lt;br /&gt;일단 이 정도까지는 알겠고, 여기서 3번 조건이 약간 함정인데 3번 조건을 무시하고 총합이 최대가 되게 선택을 한다면 어떻게 될까요? 총합이 최대가 되게 선택을 했는데 3번 조건에 모순이 생길 수 있을지 생각해봅시다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;슬라이드72.PNG&quot; data-origin-width=&quot;2000&quot; data-origin-height=&quot;1125&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cJIHCG/btsNtdDmIaM/MCysJACEbVF2nb9G47XeR0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cJIHCG/btsNtdDmIaM/MCysJACEbVF2nb9G47XeR0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cJIHCG/btsNtdDmIaM/MCysJACEbVF2nb9G47XeR0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcJIHCG%2FbtsNtdDmIaM%2FMCysJACEbVF2nb9G47XeR0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;2000&quot; height=&quot;1125&quot; data-filename=&quot;슬라이드72.PNG&quot; data-origin-width=&quot;2000&quot; data-origin-height=&quot;1125&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다행히 3번 조건을 무시하고 총합이 최대가 되게 선택을 했을 때, 모순이 발생할 수 없습니다. 지금 이 그림에서 4개 정점이 모두 우수 마을이 아니라고 가정해 봅시다. 그러면 가운데 정점은 3번 조건에 위배되는 셈입니다. 그런데 그럴 경우, 그냥 저 가운데 정점을 우수 마을로 선택해 버리면 됩니다. 인접한 정점 중에 우수 마을이 없으니까 가운데 정점을 우수 마을로 선택해도 2번 조건을 잘 만족하고 심지어 주민 수의 총합은 늘어나게 됩니다.&lt;br /&gt;&lt;br /&gt;따라서&amp;nbsp;우수&amp;nbsp;마을&amp;nbsp;주민&amp;nbsp;수의&amp;nbsp;총합을&amp;nbsp;최대로&amp;nbsp;택했다면&amp;nbsp;3번&amp;nbsp;조건은&amp;nbsp;자동으로&amp;nbsp;만족된다는&amp;nbsp;결론을&amp;nbsp;얻을&amp;nbsp;수&amp;nbsp;있습니다.&amp;nbsp;그렇다면&amp;nbsp;1번과&amp;nbsp;2번&amp;nbsp;조건만을&amp;nbsp;가지고&amp;nbsp;식을&amp;nbsp;잘&amp;nbsp;세우면&amp;nbsp;되고,&amp;nbsp;RGB거리나&amp;nbsp;스티커&amp;nbsp;문제에서의&amp;nbsp;느낌처럼&amp;nbsp;지금&amp;nbsp;보는&amp;nbsp;정점이&amp;nbsp;우수&amp;nbsp;마을일&amp;nbsp;때의&amp;nbsp;최댓값과&amp;nbsp;일반&amp;nbsp;마을일&amp;nbsp;때의&amp;nbsp;최댓값을&amp;nbsp;관리하는&amp;nbsp;방식으로&amp;nbsp;DP&amp;nbsp;식을&amp;nbsp;이끌어낼&amp;nbsp;수&amp;nbsp;있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;슬라이드73.PNG&quot; data-origin-width=&quot;2000&quot; data-origin-height=&quot;1125&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/uhhDe/btsNscMq8nF/aHoCEdrwvhiNU5wQMDxWk1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/uhhDe/btsNscMq8nF/aHoCEdrwvhiNU5wQMDxWk1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/uhhDe/btsNscMq8nF/aHoCEdrwvhiNU5wQMDxWk1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FuhhDe%2FbtsNscMq8nF%2FaHoCEdrwvhiNU5wQMDxWk1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;2000&quot; height=&quot;1125&quot; data-filename=&quot;슬라이드73.PNG&quot; data-origin-width=&quot;2000&quot; data-origin-height=&quot;1125&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;주어진 그래프가 트리 구조라고 되어 있으니 아무 정점이나 루트로 올립니다. 그리고 D1 테이블을 i번 정점이 우수 마을일 때 서브 트리에서 우수 마을 주민 수의 총합의 최대값으로 정의하고, D2 테이블을 i번 정점이 우수 마을이 아닐 때 서브 트리에서 우수 마을 주민 수의 총합의 최대값으로 정의합니다.&lt;br /&gt;&lt;br /&gt;이렇게&amp;nbsp;정의한&amp;nbsp;뒤,&amp;nbsp;D1[1]과&amp;nbsp;D2[1]을&amp;nbsp;구할&amp;nbsp;때,&amp;nbsp;D1[2],&amp;nbsp;D1[3],&amp;nbsp;D1[4],&amp;nbsp;D2[2],&amp;nbsp;D2[3],&amp;nbsp;D2[4]를&amp;nbsp;어떻게&amp;nbsp;써먹을&amp;nbsp;수&amp;nbsp;있을지&amp;nbsp;고민해&amp;nbsp;보겠습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;슬라이드74.PNG&quot; data-origin-width=&quot;2000&quot; data-origin-height=&quot;1125&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/Ose4R/btsNsTkPRfl/Uil7dK1YX6FuHGUu46drn0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/Ose4R/btsNsTkPRfl/Uil7dK1YX6FuHGUu46drn0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/Ose4R/btsNsTkPRfl/Uil7dK1YX6FuHGUu46drn0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FOse4R%2FbtsNsTkPRfl%2FUil7dK1YX6FuHGUu46drn0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;2000&quot; height=&quot;1125&quot; data-filename=&quot;슬라이드74.PNG&quot; data-origin-width=&quot;2000&quot; data-origin-height=&quot;1125&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;먼저 D1[1]을 보면, 1번 정점을 우수 마을로 두었으므로 1번 조건에 따라 2, 3, 4번 마을은 반드시 우수 마을이 아니어야 합니다. 그러면 D1[1]의 식은 바로 도출이 가능합니다. 1번 마을의 주민 수를 A라고 하면 A는 당연히 더해져야 하고 2, 3, 4번 마을에서는 각 마을이 우수 마을이 아닐 때 총합의 최대값을 가져오도록 D2[2], D2[3], D2[4]를 더해주면 됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;슬라이드75.PNG&quot; data-origin-width=&quot;2000&quot; data-origin-height=&quot;1125&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bsuyyw/btsNrV5iWmw/rndKH9WuuraIKIcMq2w53k/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bsuyyw/btsNrV5iWmw/rndKH9WuuraIKIcMq2w53k/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bsuyyw/btsNrV5iWmw/rndKH9WuuraIKIcMq2w53k/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fbsuyyw%2FbtsNrV5iWmw%2FrndKH9WuuraIKIcMq2w53k%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;2000&quot; height=&quot;1125&quot; data-filename=&quot;슬라이드75.PNG&quot; data-origin-width=&quot;2000&quot; data-origin-height=&quot;1125&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다음으로&amp;nbsp;D2[1]에서는&amp;nbsp;1번&amp;nbsp;정점을&amp;nbsp;우수&amp;nbsp;마을로&amp;nbsp;두지&amp;nbsp;않으므로&amp;nbsp;2,&amp;nbsp;3,&amp;nbsp;4번&amp;nbsp;마을은&amp;nbsp;우수&amp;nbsp;마을이어도&amp;nbsp;상관없고&amp;nbsp;아니어도&amp;nbsp;상관없습니다.&amp;nbsp;이&amp;nbsp;경우에는&amp;nbsp;D1과&amp;nbsp;D2&amp;nbsp;중에서&amp;nbsp;최댓값을&amp;nbsp;더해주면&amp;nbsp;됩니다.&amp;nbsp;그래서&amp;nbsp;식은&amp;nbsp;저기&amp;nbsp;적힌&amp;nbsp;것처럼&amp;nbsp;구할&amp;nbsp;수&amp;nbsp;있습니다.&lt;br /&gt;&lt;br /&gt;여기서 만약 max를 구한 결과 3개 마을 모두에서 D2[2], D2[3], D2[4]가 선택되면 세 마을 모두 우수 마을이 아니라는 뜻이 되므로 3번 조건과 모순이 될 수 있다는 의문이 생길 수 있습니다. 여기서 다시 한 번 정리해 드리겠습니다. 앞에서 본 것처럼 총합을 최대로 한다면 3번 조건은 자동으로 만족되므로 고려할 필요가 없다고 했습니다. 그런데 이 DP 식으로만 따지면 부분적으로는 3번 조건에 모순이 될 수 있는 경우가 있을 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;슬라이드76.PNG&quot; data-origin-width=&quot;2000&quot; data-origin-height=&quot;1125&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bvEkSL/btsNrwxVqXF/9y0Nq0NIgqE7Impu8oTOd1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bvEkSL/btsNrwxVqXF/9y0Nq0NIgqE7Impu8oTOd1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bvEkSL/btsNrwxVqXF/9y0Nq0NIgqE7Impu8oTOd1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbvEkSL%2FbtsNrwxVqXF%2F9y0Nq0NIgqE7Impu8oTOd1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;2000&quot; height=&quot;1125&quot; data-filename=&quot;슬라이드76.PNG&quot; data-origin-width=&quot;2000&quot; data-origin-height=&quot;1125&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;예를 들어, 지금처럼 트리가 1-1-5처럼 생겨 있으면 D1과 D2 값은 저렇게 됩니다. 그런데 루트의 D2 값은 제일 밑의 값이 5인 정점만 포함되므로, 이 D2 값의 상황에서는 3번 조건이 만족하지 않게 됩니다. 하지만 상관없는 것이 어차피 총합을 최대로 하면 3번 조건은 자동으로 만족한다는 것을 알기 때문에 저 D2 값은 답을 구할 때 사용되지 않습니다. 이처럼 DP를 계산하는 중간에는 3번 조건이 만족하지 않을 수 있습니다. 하지만 최종 답에는 어차피 3번 조건이 만족되므로, 이 조건을 신경 쓸 필요는 없습니다. 3번 조건은 그냥 없는 조건으로 생각하고 문제를 풀면 됩니다.&lt;br /&gt;&lt;br /&gt;그리고 DP에서는 항상 테이블 정의와 식을 찾을 뿐만 아니라, 초기값과 채우는 순서도 생각해야 합니다. 식의 특성상 자식의 DP 값이 먼저 구해져야 하므로 밑에서부터 값을 채워나가면 됩니다. 또한 초기값은 리프 정점들에서 자명하게 정해지니까 이것들을 어떻게 처리할지는 코드를 보면서 이해해 보면 됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;슬라이드77.PNG&quot; data-origin-width=&quot;2000&quot; data-origin-height=&quot;1125&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dnwcef/btsNsUKPIpz/D1Qu80tySI3Fbfu7yZP9hK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dnwcef/btsNsUKPIpz/D1Qu80tySI3Fbfu7yZP9hK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dnwcef/btsNsUKPIpz/D1Qu80tySI3Fbfu7yZP9hK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fdnwcef%2FbtsNsUKPIpz%2FD1Qu80tySI3Fbfu7yZP9hK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;2000&quot; height=&quot;1125&quot; data-filename=&quot;슬라이드77.PNG&quot; data-origin-width=&quot;2000&quot; data-origin-height=&quot;1125&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;어쩌면&amp;nbsp;잊고&amp;nbsp;있을&amp;nbsp;수도&amp;nbsp;있는&amp;nbsp;트리에서의&amp;nbsp;DFS&amp;nbsp;순회를&amp;nbsp;이용한&amp;nbsp;구현은&amp;nbsp;좀&amp;nbsp;더&amp;nbsp;편리할&amp;nbsp;수&amp;nbsp;있습니다.&amp;nbsp;이는&amp;nbsp;사실상&amp;nbsp;top-down&amp;nbsp;방식이라고&amp;nbsp;볼&amp;nbsp;수도&amp;nbsp;있습니다.&amp;nbsp;1번을&amp;nbsp;루트로&amp;nbsp;잡고&amp;nbsp;DFS를&amp;nbsp;돌면서&amp;nbsp;계속&amp;nbsp;자식으로&amp;nbsp;내려갑니다.&amp;nbsp;리프&amp;nbsp;정점까지&amp;nbsp;도달하면&amp;nbsp;더&amp;nbsp;이상&amp;nbsp;자식이&amp;nbsp;없으므로,&amp;nbsp;그&amp;nbsp;시점에서&amp;nbsp;d1[cur]&amp;nbsp;=&amp;nbsp;a[cur],&amp;nbsp;d2[cur]&amp;nbsp;=&amp;nbsp;0으로&amp;nbsp;설정한&amp;nbsp;뒤&amp;nbsp;함수가&amp;nbsp;끝납니다.&lt;br /&gt;&lt;br /&gt;그리고&amp;nbsp;트리에서&amp;nbsp;DFS의&amp;nbsp;특성상&amp;nbsp;DFS&amp;nbsp;함수&amp;nbsp;호출이&amp;nbsp;일어날&amp;nbsp;때마다&amp;nbsp;각&amp;nbsp;정점은&amp;nbsp;처음&amp;nbsp;방문한&amp;nbsp;상태이기&amp;nbsp;때문에,&amp;nbsp;원래&amp;nbsp;top-down에서&amp;nbsp;하던&amp;nbsp;것처럼&amp;nbsp;d1[cur]이&amp;nbsp;이미&amp;nbsp;계산된&amp;nbsp;것인지&amp;nbsp;확인할&amp;nbsp;필요가&amp;nbsp;없습니다.&amp;nbsp;만약&amp;nbsp;이&amp;nbsp;DFS&amp;nbsp;코드가&amp;nbsp;헷갈린다면,&amp;nbsp;트리&amp;nbsp;단원을&amp;nbsp;다시&amp;nbsp;보고&amp;nbsp;오시는&amp;nbsp;것을&amp;nbsp;추천드립니다.&lt;br /&gt;&lt;br /&gt;이렇게&amp;nbsp;계산을&amp;nbsp;마친&amp;nbsp;후에는&amp;nbsp;d1[1]과&amp;nbsp;d2[1]&amp;nbsp;중&amp;nbsp;최대값을&amp;nbsp;반환하면&amp;nbsp;그것이&amp;nbsp;바로&amp;nbsp;답입니다.&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;슬라이드78.PNG&quot; data-origin-width=&quot;2000&quot; data-origin-height=&quot;1125&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bwdL18/btsNtfnEHbc/EENPw4n2CIYxaT3HOHKJU1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bwdL18/btsNtfnEHbc/EENPw4n2CIYxaT3HOHKJU1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bwdL18/btsNtfnEHbc/EENPw4n2CIYxaT3HOHKJU1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbwdL18%2FbtsNtfnEHbc%2FEENPw4n2CIYxaT3HOHKJU1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;2000&quot; height=&quot;1125&quot; data-filename=&quot;슬라이드78.PNG&quot; data-origin-width=&quot;2000&quot; data-origin-height=&quot;1125&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;드디어 마지막 위상 정렬 DP입니다. 위상 정렬이 무엇인지 기억을 되새겨보면, 방향 그래프, 구체적으로는 DAG에서 선후 관계에 모순이 없게 나열하는 정렬입니다. 그리고 이 선후 관계에 따라 DP 식이 정해지는 상황에서는 위상 정렬을 하는 과정에서 테이블도 함께 채워나가는 방식으로 위상 정렬 DP를 수행할 수 있습니다. 이제 문제를 보면서 상황을 이해해보겠습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;슬라이드79.PNG&quot; data-origin-width=&quot;2000&quot; data-origin-height=&quot;1125&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cLrSav/btsNr991wlr/fy0sgqZHZ4hmQEwkXZ9DbK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cLrSav/btsNr991wlr/fy0sgqZHZ4hmQEwkXZ9DbK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cLrSav/btsNr991wlr/fy0sgqZHZ4hmQEwkXZ9DbK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcLrSav%2FbtsNr991wlr%2Ffy0sgqZHZ4hmQEwkXZ9DbK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;2000&quot; height=&quot;1125&quot; data-filename=&quot;슬라이드79.PNG&quot; data-origin-width=&quot;2000&quot; data-origin-height=&quot;1125&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://www.acmicpc.net/problem/1005&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;BOJ 1005번: ACM Craft&lt;/a&gt; 문제를 보면 스타가 하고 싶습니다. 문득 드는 생각이 아무래도 강의를 듣는 사람들의 나이대는 계속 비슷하니까 시간이 지나면 지날수록 시청자층과 저의 나이 차이가 점점 커지게 됩니다. 그러면 저희 세대야 캐리어 뽑으면 이긴다 이런 표현을 하면 대부분 알아듣지만 몇 년 지나면 시간이 지나면 이 말이 무슨 뜻인지 모르는 사람들의 비율이 더 커지겠죠? 급 슬픕니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;아무튼 문제를 보면, 식이 쉽게 감이 옵니다. 슬라이드의 그림처럼 건물 번호가 붙어 있다고 할 때 D[i]를 i번째 건물이 지어지기 위해 필요한 최소 시간이라고 정의할 수 있습니다. 여기서 D[5]를 계산하려면 4번과 6번 건물이 지어져 있어야 합니다. 문제 조건에서 건설을 동시에 할 수 있다고 하니 4번과 6번 각각 최소 시간으로 지은 후 둘 중 더 오래 걸리는게 지어지는 즉시 5번을 지으면 됩니다. 5번 건물을 짓는 데 걸리는 시간을 A라고 하면, D[5] = A + max(D[4], D[6])라는 식을 얻을 수 있습니다.&lt;br /&gt;&lt;br /&gt;나에게 들어오는 정점들 중에서 최댓값을 구하기만 하면 되고, 초기값은 indegree가 0인 정점, 이 그림에서는 1번과 6번 정점에서 채울 수 있습니다. 테이블을 채우는 순서는 위상 정렬을 직접 수행하는 대신 top-down 방식으로 알아서 처리되게끔 할 수 있습니다. 이제 코드를 보며 더 구체적으로 이해해 보겠습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;슬라이드80.PNG&quot; data-origin-width=&quot;2000&quot; data-origin-height=&quot;1125&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/Cu7un/btsNr23iDrL/Q6Y7en3bvIvFcoKeWKSoTK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/Cu7un/btsNr23iDrL/Q6Y7en3bvIvFcoKeWKSoTK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/Cu7un/btsNr23iDrL/Q6Y7en3bvIvFcoKeWKSoTK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FCu7un%2FbtsNr23iDrL%2FQ6Y7en3bvIvFcoKeWKSoTK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;2000&quot; height=&quot;1125&quot; data-filename=&quot;슬라이드80.PNG&quot; data-origin-width=&quot;2000&quot; data-origin-height=&quot;1125&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;코드를 보면 참 깔끔하게 잘 짰네요. 누가 짰는지..ㅎㅎ 기본적인 흐름은 top-down DP에서 설명한 상황과 완전히 똑같습니다. adj[x]에는 x로 들어오는 정점들의 목록을 두고, go(x)에서 d[x]를 구하는데 adj[x]를 쭉 보면서 그 d 값들을 참고하면 됩니다. 그리고 10, 11번째 줄의 처리로 중복된 계산을 막아줍니다.&lt;br /&gt;&lt;br /&gt;시간&amp;nbsp;복잡도를&amp;nbsp;따지면,&amp;nbsp;각&amp;nbsp;정점에서&amp;nbsp;d&amp;nbsp;값은&amp;nbsp;한&amp;nbsp;번만&amp;nbsp;계산되고,&amp;nbsp;d&amp;nbsp;값을&amp;nbsp;구할&amp;nbsp;때&amp;nbsp;자식의&amp;nbsp;개수만큼&amp;nbsp;시간이&amp;nbsp;걸립니다.&amp;nbsp;그러면&amp;nbsp;전체&amp;nbsp;정점들에서&amp;nbsp;자식의&amp;nbsp;개수의&amp;nbsp;합은&amp;nbsp;간선의&amp;nbsp;개수와&amp;nbsp;똑같으니,&amp;nbsp;시간&amp;nbsp;복잡도는&amp;nbsp;O(V&amp;nbsp;+&amp;nbsp;E)입니다.&amp;nbsp;물론&amp;nbsp;이걸&amp;nbsp;위상&amp;nbsp;정렬을&amp;nbsp;수행하고&amp;nbsp;위상&amp;nbsp;정렬&amp;nbsp;순서대로&amp;nbsp;테이블을&amp;nbsp;채워&amp;nbsp;나가는&amp;nbsp;방식으로&amp;nbsp;해결할&amp;nbsp;수도&amp;nbsp;있지만,&amp;nbsp;그것보다는&amp;nbsp;지금처럼&amp;nbsp;top-down&amp;nbsp;방식으로&amp;nbsp;푸는&amp;nbsp;것이&amp;nbsp;코드가&amp;nbsp;훨씬&amp;nbsp;간결하므로&amp;nbsp;이렇게&amp;nbsp;푸는&amp;nbsp;걸&amp;nbsp;추천드립니다.&lt;br /&gt;&lt;br /&gt;그리고 응용력이 굉장히 좋은 분이라면 이 방식을 보고, &quot;어, 그럼 반대로 위상 정렬을 원래 하던 대로 큐를 쓰는 것이 아니라 top-down으로 짜면 더 간결하지 않을까?&quot;라는 생각을 할 수도 있을 것 같습니다. 실제로 이렇게 top-down 방식으로 위상 정렬을 수행할 수도 있고, 또 코드가 기존 방식보다 더 간결하다는 장점이 있습니다. 이건 그냥 살짝 TMI 느낌으로, &quot;아, 그렇구나&quot; 정도로 언급드린 걸로 끝내겠습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;슬라이드81.PNG&quot; data-origin-width=&quot;2000&quot; data-origin-height=&quot;1125&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/xCMHu/btsNrvZ0QZK/lWBBSof5gpkfONnIdZTpkk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/xCMHu/btsNrvZ0QZK/lWBBSof5gpkfONnIdZTpkk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/xCMHu/btsNrvZ0QZK/lWBBSof5gpkfONnIdZTpkk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FxCMHu%2FbtsNrvZ0QZK%2FlWBBSof5gpkfONnIdZTpkk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;2000&quot; height=&quot;1125&quot; data-filename=&quot;슬라이드81.PNG&quot; data-origin-width=&quot;2000&quot; data-origin-height=&quot;1125&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;정말 수고 많으셨습니다! 작성하다보니 이것도 설명하고 싶고 저것도 설명하고 싶고 해서 분량이 상당히 길어졌습니다. 아무튼 도움이 되셨길 바라며 이만 마치겠습니다. 행복하세요~~&lt;/p&gt;</description>
      <category>강좌/실전 알고리즘</category>
      <author>BaaaaaaaaaaaaaaaaaaaaaaarkingDog</author>
      <guid isPermaLink="true">https://baaaaaaaaaaaaaaaaaaaaaaarkingdog.tistory.com/1101</guid>
      <comments>https://baaaaaaaaaaaaaaaaaaaaaaarkingdog.tistory.com/1101#entry1101comment</comments>
      <pubDate>Sun, 20 Apr 2025 00:28:30 +0900</pubDate>
    </item>
    <item>
      <title>3/15-3/23 로마</title>
      <link>https://baaaaaaaaaaaaaaaaaaaaaaarkingdog.tistory.com/1100</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://fse.iacr.org/2025/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;FSE 2025&lt;/a&gt; 학회에 참석해서 로마에 갔다. 겸사겸사 관광도 했다. 좋았지만 돌아오기 하루 이틀전에는 슬슬 한국에 가고싶었어서 아쉬움 안남기고 딱 적당한 일정으로 잘 갔다온 기분이다. 음식은 거의 다 이탈리안으로 먹었는데 맛있었지만 계속 먹다보니 질렸다. 한식도 일주일 내내 먹으면 질릴듯.. 마지막날 빼고 날씨는 계속 좋았다. 아무튼 재밌었다 bb&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;4000&quot; data-origin-height=&quot;3000&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dUm3c6/btsMUvsl0su/wDwsLmoOw7oSEbrpCylnh0/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dUm3c6/btsMUvsl0su/wDwsLmoOw7oSEbrpCylnh0/img.jpg&quot; data-alt=&quot;관공서인듯?&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dUm3c6/btsMUvsl0su/wDwsLmoOw7oSEbrpCylnh0/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdUm3c6%2FbtsMUvsl0su%2FwDwsLmoOw7oSEbrpCylnh0%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;4000&quot; height=&quot;3000&quot; data-origin-width=&quot;4000&quot; data-origin-height=&quot;3000&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;관공서인듯?&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;3000&quot; data-origin-height=&quot;4000&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/oOMYW/btsMT7L1v1F/fjA0iUrdPHOl4QJNbr5250/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/oOMYW/btsMT7L1v1F/fjA0iUrdPHOl4QJNbr5250/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/oOMYW/btsMT7L1v1F/fjA0iUrdPHOl4QJNbr5250/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FoOMYW%2FbtsMT7L1v1F%2FfjA0iUrdPHOl4QJNbr5250%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;3000&quot; height=&quot;4000&quot; data-origin-width=&quot;3000&quot; data-origin-height=&quot;4000&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;3000&quot; data-origin-height=&quot;4000&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cjDgF8/btsMT5HtW5a/zh9u1fk5QGLtl19DAHeRz1/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cjDgF8/btsMT5HtW5a/zh9u1fk5QGLtl19DAHeRz1/img.jpg&quot; data-alt=&quot;살아있는 갈매기입니다,,&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cjDgF8/btsMT5HtW5a/zh9u1fk5QGLtl19DAHeRz1/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcjDgF8%2FbtsMT5HtW5a%2Fzh9u1fk5QGLtl19DAHeRz1%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;3000&quot; height=&quot;4000&quot; data-origin-width=&quot;3000&quot; data-origin-height=&quot;4000&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;살아있는 갈매기입니다,,&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;3000&quot; data-origin-height=&quot;4000&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cBEwp6/btsMWkQwEYO/HSqsx5hSFkAIkocqChh65K/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cBEwp6/btsMWkQwEYO/HSqsx5hSFkAIkocqChh65K/img.jpg&quot; data-alt=&quot;싸고 맛있었음&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cBEwp6/btsMWkQwEYO/HSqsx5hSFkAIkocqChh65K/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcBEwp6%2FbtsMWkQwEYO%2FHSqsx5hSFkAIkocqChh65K%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;3000&quot; height=&quot;4000&quot; data-origin-width=&quot;3000&quot; data-origin-height=&quot;4000&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;싸고 맛있었음&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2252&quot; data-origin-height=&quot;4000&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/PwkLl/btsMVEaNc83/1Ax9BOxouPcEkqqzKuQw11/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/PwkLl/btsMVEaNc83/1Ax9BOxouPcEkqqzKuQw11/img.jpg&quot; data-alt=&quot;학회에서 준 노트인데 그냥 호텔에 버리고 귀국ㅠㅠ&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/PwkLl/btsMVEaNc83/1Ax9BOxouPcEkqqzKuQw11/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FPwkLl%2FbtsMVEaNc83%2F1Ax9BOxouPcEkqqzKuQw11%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;2252&quot; height=&quot;4000&quot; data-origin-width=&quot;2252&quot; data-origin-height=&quot;4000&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;학회에서 준 노트인데 그냥 호텔에 버리고 귀국ㅠㅠ&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;4000&quot; data-origin-height=&quot;3000&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/UnTX5/btsMVtHrdoF/rGugwJM8OBNOukq0Jkmkr0/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/UnTX5/btsMVtHrdoF/rGugwJM8OBNOukq0Jkmkr0/img.jpg&quot; data-alt=&quot;나폴리. 3대 미항이라고 하는데, 예쁘긴한데 그정돈가...?&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/UnTX5/btsMVtHrdoF/rGugwJM8OBNOukq0Jkmkr0/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FUnTX5%2FbtsMVtHrdoF%2FrGugwJM8OBNOukq0Jkmkr0%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;4000&quot; height=&quot;3000&quot; data-origin-width=&quot;4000&quot; data-origin-height=&quot;3000&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;나폴리. 3대 미항이라고 하는데, 예쁘긴한데 그정돈가...?&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;4000&quot; data-origin-height=&quot;3000&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/v2PiB/btsMWsVgF8n/Oj79xXuJC8H7pckAU8Zzv0/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/v2PiB/btsMWsVgF8n/Oj79xXuJC8H7pckAU8Zzv0/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/v2PiB/btsMWsVgF8n/Oj79xXuJC8H7pckAU8Zzv0/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fv2PiB%2FbtsMWsVgF8n%2FOj79xXuJC8H7pckAU8Zzv0%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;4000&quot; height=&quot;3000&quot; data-origin-width=&quot;4000&quot; data-origin-height=&quot;3000&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;</description>
      <category>일상/ETC</category>
      <author>BaaaaaaaaaaaaaaaaaaaaaaarkingDog</author>
      <guid isPermaLink="true">https://baaaaaaaaaaaaaaaaaaaaaaarkingdog.tistory.com/1100</guid>
      <comments>https://baaaaaaaaaaaaaaaaaaaaaaarkingdog.tistory.com/1100#entry1100comment</comments>
      <pubDate>Tue, 25 Mar 2025 06:06:04 +0900</pubDate>
    </item>
    <item>
      <title>사는 얘기</title>
      <link>https://baaaaaaaaaaaaaaaaaaaaaaarkingdog.tistory.com/1099</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;figure data-ke-type=&quot;video&quot; data-ke-style=&quot;alignCenter&quot; data-video-host=&quot;youtube&quot; data-video-url=&quot;https://www.youtube.com/watch?v=yWDB9t6RIHE&quot; data-video-thumbnail=&quot;https://scrap.kakaocdn.net/dn/b21XCm/hyX7WyA0OC/xYB6p5C1GOaiK3SxBI5Gz0/img.jpg?width=1280&amp;amp;height=720&amp;amp;face=338_108_538_326,https://scrap.kakaocdn.net/dn/dSji1d/hyX7Vfmr5v/WLVdefRZQS2bRBsktxKA0k/img.jpg?width=1280&amp;amp;height=720&amp;amp;face=338_108_538_326&quot; data-video-width=&quot;860&quot; data-video-height=&quot;484&quot; data-video-origin-width=&quot;860&quot; data-video-origin-height=&quot;484&quot; data-ke-mobilestyle=&quot;widthContent&quot; data-video-title=&quot;건물 사이에 피어난 장미(Rose Blossom) l DRW Band Cover&quot; data-original-url=&quot;&quot;&gt;&lt;iframe src=&quot;https://www.youtube.com/embed/yWDB9t6RIHE&quot; width=&quot;860&quot; height=&quot;484&quot; frameborder=&quot;&quot; allowfullscreen=&quot;true&quot;&gt;&lt;/iframe&gt;
&lt;figcaption style=&quot;display: none;&quot;&gt;&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이번 연휴때 정말 알차게 잘 쉬었습니다. 2월 중순에 마감인 학회가 있어서 사실 연휴때 일을 하면 좋긴했는데 에라 모르겠다 다음주부터 열심히하지 뭐 라고 생각하며 재충전의 시간으로 삼았습니다. 본가에 가서 처음 한 3일 정도는 이게 맞나 .. 싶을정도로 자도 자도 피곤해서 틈만나면 낮잠 계속자고 밤에도 자고 그랬네요. 아무튼 친형이랑 이재모피자도 먹고 방탈출도 하고 적당한 휴식과 컨텐츠가 잘 어우러진 그런 연휴를 보냈습니다. 저번주 주말부터 해서 오래 쉬었는데 내일도 일요일이라니 기분이 좋네요&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;ㅡ&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 글을 쓰게 된 주 계기이기도 한데, eurocrypt에 두 편 낸게 전부 억셉됐습니다. 한 편은 리뷰가 매우 좋게 왔어서 붙을거라 예상하고 있었지만 다른 한 편은 editorial quality, motivation, main idea 등은 괜찮은 반면 제안한 구조의 security analysis의 설득력이 부족하다는 리뷰를 받았었습니다(그것도 I believe the paper should not be accepted until it makes clear claims about the security of the proposed scheme 라고 꽤 직설적으로,,) 그래도 아예 기존꺼랑 차별점이 없다라던가 motivation이 약하다 이래버리면 논문 자체를 뜯어고쳐야할수도 있는데 리뷰를 보니 내용 자체에는 동의를 해주어서 아마 리젝은 되겠지만 security analysis를 보완해서 다음 학회에 내면 되겠다고 생각을 하고 있었습니다. 그런데 완전 예상치못하게 억셉이 되어서...ㅎㅎㅎ 처음으로 제가 주도해서 작성한거라 정말 소중한 논문이었는데 한방에 붙어버려서 정말 기쁘네요. 5월에 마드리드가서 발표를 하게 되었습니다  2022년에 eurocrypt에 참석해서 아래와 같은 트위터 글을 썼는데 3년만에 이루어냈네요. 졸업 전에 한 편 더 쓸 수 있도록 남은 기간도 화이팅&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;589&quot; data-origin-height=&quot;446&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/byJFBY/btsL3igQXuy/CXQLOmP8KYfM1iEblSYIG1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/byJFBY/btsL3igQXuy/CXQLOmP8KYfM1iEblSYIG1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/byJFBY/btsL3igQXuy/CXQLOmP8KYfM1iEblSYIG1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbyJFBY%2FbtsL3igQXuy%2FCXQLOmP8KYfM1iEblSYIG1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;589&quot; height=&quot;446&quot; data-origin-width=&quot;589&quot; data-origin-height=&quot;446&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;ㅡ&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이제와서 말하는거지만 작년 연말이 약간 좀 슬럼프였습니다. 약간 심적으로 힘든 일도 있었고,, 엄청 특별한건 아니고 흔히 있을 수 있는 일이었는데 거기에 더해서 당시 사회 분위기도 이래저래 쳐지고 감기도 걸리고 해서 꾸역꾸역 출퇴근은 하지만 능률은 0에 수렴하는 상태로 연말을 되게 허무하게 보냈습니다. 연말이나 연초에 1년을 되돌아보는 글을 쓰곤 했는데 올해에는 연초에 상황이 이랬어서 혼자 일기나 쓰고 블로그는 건너뛰게 됐네요. 이래나저래나 뭐 시간이 약인 것 같습니다. 지금은 ㄱㅊ.. 블로그에 너무 막 부정적인 얘기를 한가득 적고싶지도 않고 그렇다고 또 무슨 나 잘났다 얘기만 써놓는것도 원하는건 아니어서 그냥 지금처럼 잔잔하게 흘러가는 사는 얘기나 간간히 남기려고 합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;ㅡ&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;4월말에 있는 하프마라톤을 신청했습니다. 홈그라운드의 이점을 살려 부산에서 열리는걸로,, 추위를 좀 많이 타서 기온이 한 5도 밑으로 내려가면 도저히 뛸 엄두를 못내겠어서 겨울에 많이 못뛰었는데 날 풀리면 다시 열심히 뛰어야겠습니다. 내일도 친구랑 뛰기로 했는데, 예보에 최고 기온이 10도인거 보고 정오쯤 뛰기로 약속했는데 기온을 보니 12시에는 4도네요 흐 잘 껴입고 달려야할듯.. 마침 베이퍼플라이3 주문한것도 오늘 배송와서 딱 내일 개시를 하면 되는 상황입니다. 궁극적으로는 가을에 풀코스를 완주하는게 목표여서 LSD를 하면서 계속 거리를 늘려나가려고 합니다. 크로스핏도 어영부영하다보니 몇달 쉬었는데 다음주부터 다시 다녀야겠습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;ㅡ&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그럼 올 한해도 같이 화이팅합시다 으라차차,,,^^~~&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>일상/의식의 흐름</category>
      <author>BaaaaaaaaaaaaaaaaaaaaaaarkingDog</author>
      <guid isPermaLink="true">https://baaaaaaaaaaaaaaaaaaaaaaarkingdog.tistory.com/1099</guid>
      <comments>https://baaaaaaaaaaaaaaaaaaaaaaarkingdog.tistory.com/1099#entry1099comment</comments>
      <pubDate>Sun, 2 Feb 2025 01:38:16 +0900</pubDate>
    </item>
    <item>
      <title>생전고인의개쩌는위도우</title>
      <link>https://baaaaaaaaaaaaaaaaaaaaaaarkingdog.tistory.com/1098</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;figure data-ke-type=&quot;video&quot; data-ke-style=&quot;alignCenter&quot; data-video-host=&quot;kakaotv&quot; data-video-url=&quot;https://tv.kakao.com/v/450841439&quot; data-video-thumbnail=&quot;https://scrap.kakaocdn.net/dn/GkVms/hyXwh3xCC0/tKTBeRW9kjSnFCRNx7sbQK/img.jpg?width=1920&amp;amp;height=1080&amp;amp;face=0_0_1920_1080,https://scrap.kakaocdn.net/dn/bhLFAz/hyXwf5IrW3/hXC1qxNIqCoEcWUKHxsa91/img.jpg?width=1920&amp;amp;height=1080&amp;amp;face=0_0_1920_1080&quot; data-video-width=&quot;860&quot; data-video-height=&quot;484&quot; data-video-origin-width=&quot;860&quot; data-video-origin-height=&quot;484&quot; data-ke-mobilestyle=&quot;widthContent&quot; data-video-play-service=&quot;daum_tistory&quot; data-original-url=&quot;&quot; data-video-title=&quot;&quot;&gt;&lt;iframe src=&quot;https://play-tv.kakao.com/embed/player/cliplink/450841439?service=daum_tistory&quot; width=&quot;860&quot; height=&quot;484&quot; frameborder=&quot;0&quot; allowfullscreen=&quot;true&quot;&gt;&lt;/iframe&gt;
&lt;figcaption style=&quot;display: none;&quot;&gt;&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;figure data-ke-type=&quot;video&quot; data-ke-style=&quot;alignCenter&quot; data-video-host=&quot;kakaotv&quot; data-video-url=&quot;https://tv.kakao.com/v/450841446&quot; data-video-thumbnail=&quot;https://scrap.kakaocdn.net/dn/bMGZNo/hyXwoVUoHb/f7whpqPwq93GkhvQrSPLIK/img.jpg?width=1920&amp;amp;height=1080&amp;amp;face=0_0_1920_1080,https://scrap.kakaocdn.net/dn/pDiOu/hyXwwfk2aD/G849RvvJL6zUhMWMjN3U9K/img.jpg?width=1920&amp;amp;height=1080&amp;amp;face=0_0_1920_1080&quot; data-video-width=&quot;860&quot; data-video-height=&quot;484&quot; data-video-origin-width=&quot;860&quot; data-video-origin-height=&quot;484&quot; data-ke-mobilestyle=&quot;widthContent&quot; data-video-play-service=&quot;daum_tistory&quot; data-original-url=&quot;&quot; data-video-title=&quot;&quot;&gt;&lt;iframe src=&quot;https://play-tv.kakao.com/embed/player/cliplink/450841446?service=daum_tistory&quot; width=&quot;860&quot; height=&quot;484&quot; frameborder=&quot;0&quot; allowfullscreen=&quot;true&quot;&gt;&lt;/iframe&gt;
&lt;figcaption style=&quot;display: none;&quot;&gt;&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;ㄷㄷㄷㄷㄷ&lt;/p&gt;</description>
      <category>일상/ETC</category>
      <author>BaaaaaaaaaaaaaaaaaaaaaaarkingDog</author>
      <guid isPermaLink="true">https://baaaaaaaaaaaaaaaaaaaaaaarkingdog.tistory.com/1098</guid>
      <comments>https://baaaaaaaaaaaaaaaaaaaaaaarkingdog.tistory.com/1098#entry1098comment</comments>
      <pubDate>Sun, 10 Nov 2024 19:44:44 +0900</pubDate>
    </item>
    <item>
      <title>[실전 알고리즘] 부록 D - Union-Find</title>
      <link>https://baaaaaaaaaaaaaaaaaaaaaaarkingdog.tistory.com/1097</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;figure data-ke-type=&quot;video&quot; data-ke-style=&quot;alignCenter&quot; data-video-host=&quot;youtube&quot; data-video-url=&quot;https://www.youtube.com/watch?v=rE-OUyZJgOk&quot; data-video-thumbnail=&quot;https://scrap.kakaocdn.net/dn/cpKByv/hyXpsS33SA/RxdLNKqCXDwJP1Xuk0QxN0/img.jpg?width=1280&amp;amp;height=720&amp;amp;face=0_0_1280_720,https://scrap.kakaocdn.net/dn/c4luIZ/hyXprfwQiC/Efp2teDfOUhJ9FKdPgJS0K/img.jpg?width=1280&amp;amp;height=720&amp;amp;face=0_0_1280_720&quot; data-video-width=&quot;860&quot; data-video-height=&quot;484&quot; data-video-origin-width=&quot;860&quot; data-video-origin-height=&quot;484&quot; data-ke-mobilestyle=&quot;widthContent&quot; data-video-title=&quot;[바킹독의 실전 알고리즘] 부록 D - Union-Find&quot; data-original-url=&quot;&quot;&gt;&lt;iframe src=&quot;https://www.youtube.com/embed/rE-OUyZJgOk&quot; width=&quot;860&quot; height=&quot;484&quot; frameborder=&quot;&quot; allowfullscreen=&quot;true&quot;&gt;&lt;/iframe&gt;
&lt;figcaption style=&quot;display: none;&quot;&gt;&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cQc9p6/btsKtp257f2/DaKv2H5aVLkF9mUZ7vrAaK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cQc9p6/btsKtp257f2/DaKv2H5aVLkF9mUZ7vrAaK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cQc9p6/btsKtp257f2/DaKv2H5aVLkF9mUZ7vrAaK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcQc9p6%2FbtsKtp257f2%2FDaKv2H5aVLkF9mUZ7vrAaK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1920&quot; height=&quot;1080&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;네 반갑습니다. 이번 부록 D에서는 Union-Find 자료구조를 익혀보겠습니다. 지금까지 부록 A, B, C는 크게 까다로운 것 없이 되게 무난했는데 이번 부록 내용은 원래 강의 단원에 넣기에는 좀 난이도가 있어서 뺐던 내용이라 아마 좀 어려울 수도 있습니다. 물론 그렇다고 해서 진짜 뭐 말도 안되게 어렵다거나, 한번 봐서는 이해가 힘들거다 이정도 수준은 아니기 때문에 너무 걱정은 하지 마시고 천천히 같이 익혀보겠습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bkQ91U/btsKudm7q2G/cPeneBxmg6cx7IcNGMcAN0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bkQ91U/btsKudm7q2G/cPeneBxmg6cx7IcNGMcAN0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bkQ91U/btsKudm7q2G/cPeneBxmg6cx7IcNGMcAN0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbkQ91U%2FbtsKudm7q2G%2FcPeneBxmg6cx7IcNGMcAN0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1920&quot; height=&quot;1080&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;먼저 Union-Find 자료구조가 무엇이고 어떤 연산을 지원하는지를 살펴보고 다음으로 각 연산이 어떻게 구현되는지를 볼 예정입니다. 사실 Union-Find에서 가장 중요한건 최적화를 통해서 시간복잡도를 떨구는 것이기 때문에 해당 부분도 보고 연습문제를 풀어보면 강의가 끝납니다. 그래서 사실상 부록이라기 보다는 자료구조를 익히는 정규 단원 한 단원을 더 배운다라고 생각하면 됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bvHjct/btsKvfqKVfj/7BKc55ykwpyRl0tFvYKjD1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bvHjct/btsKvfqKVfj/7BKc55ykwpyRl0tFvYKjD1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bvHjct/btsKvfqKVfj/7BKc55ykwpyRl0tFvYKjD1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbvHjct%2FbtsKvfqKVfj%2F7BKc55ykwpyRl0tFvYKjD1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1920&quot; height=&quot;1080&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Union-Find, 혹은 Disjoint-set 이라고 부르는 이 자료구조가 무엇인지를 알아보기 전에 이 강의에서 Union-Find가 처음 등장했던 순간을 잠깐 회상해보겠습니다. 강의에서 Union-Find가 처음 나온건 0x1B강 최소 신장 트리 단원이었는데, 당시에 크루스칼 알고리즘을 익히면서 효율적인 구현을 하기 위해서는 Union-Find 자료구조가 필요하다고 언급했습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cr6loh/btsKuSij4G3/qMQpw5cSFa8KLq91d3OvD0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cr6loh/btsKuSij4G3/qMQpw5cSFa8KLq91d3OvD0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cr6loh/btsKuSij4G3/qMQpw5cSFa8KLq91d3OvD0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fcr6loh%2FbtsKuSij4G3%2FqMQpw5cSFa8KLq91d3OvD0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1920&quot; height=&quot;1080&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;크루스칼 알고리즘은 가장 비용이 낮은 간선부터 시작해 간선을 크기 순으로 살펴보며 서로 떨어져있던 정점들을 합쳐나가서 최소 신장 트리를 만들어내는 알고리즘입니다. 정점의 색깔이 그룹을 나타낸다고 했을 때, 1과 4를 연결하는 간선을 살펴본 후 두 정점의 색을 같게 만든 것이 정점을 합친 것을 나타냅니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;크루스칼 알고리즘 과정에서 우리가 계속 해야하는 연산은 두 정점이 같은 그룹인지 아닌지 확인하고, 다른 그룹이라면 둘을 합치는 연산입니다. 이걸 Flood Fill로 구현을 하면 O(V+E)의 시간이 필요하지만 Union-Find를 이용하면 두 연산 모두를 사실상 상수 시간에 가까운 속도로 처리할 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/OsuxK/btsKvqr66FT/c3aeaYQZe7uFSkgz4FbsZk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/OsuxK/btsKvqr66FT/c3aeaYQZe7uFSkgz4FbsZk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/OsuxK/btsKvqr66FT/c3aeaYQZe7uFSkgz4FbsZk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FOsuxK%2FbtsKvqr66FT%2Fc3aeaYQZe7uFSkgz4FbsZk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1920&quot; height=&quot;1080&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;정리를 해보면 Union-Find에서 지원하는 연산은 말 그대로 Union 연산과 Find 연산 이 2개입니다. Union 연산은 두 그룹을 합치는 연산이고 Find 연산은 특정 원소가 속해 있는 그룹을 알아내는 연산을 말합니다. 크루스칼 알고리즘에서는 두 정점이 같은 그룹인지를 확인하는게 필요하다고 했는데, 두 정점 각각에 대해 Find 연산을 수행하고 나면 자연스럽게 두 정점이 같은 그룹인지를 알 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cqaOBb/btsKtqnoelh/bWHS3iGVyhsnt45QrTT1Rk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cqaOBb/btsKtqnoelh/bWHS3iGVyhsnt45QrTT1Rk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cqaOBb/btsKtqnoelh/bWHS3iGVyhsnt45QrTT1Rk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcqaOBb%2FbtsKtqnoelh%2FbWHS3iGVyhsnt45QrTT1Rk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1920&quot; height=&quot;1080&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이걸 직관적으로 구현을 한다고 하면, 배열에 각 원소의 그룹 번호를 써둔 다음에 Union이나 Find 연산이 주어질 때 마다 이 값을 가지고 처리를 하는 방식을 먼저 생각을 할 수 있습니다. 일단 처음에는 각 원소의 그룹 번호가 다 다르다고 쳐서 이렇게 세팅을 해둘 수 있습니다. Find 연산의 경우에는 그냥 연산이 들어올 때 마다 배열에 적힌 값을 반환해주면 되니 따로 언급할 것이 없고, Union 연산이 중요한데 여기서&amp;nbsp;1과&amp;nbsp;5를&amp;nbsp;Union하면&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cfaG43/btsKvaQz3Re/tKE5vuKGyt6ZF0rGD4GWoK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cfaG43/btsKvaQz3Re/tKE5vuKGyt6ZF0rGD4GWoK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cfaG43/btsKvaQz3Re/tKE5vuKGyt6ZF0rGD4GWoK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcfaG43%2FbtsKvaQz3Re%2FtKE5vuKGyt6ZF0rGD4GWoK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1920&quot; height=&quot;1080&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이렇게 5번 원소의 그룹을 1로 바꿔주면 됩니다. 편의상 이번 예시에서는 Union을 할 때 뒷쪽 원소의 그룹을 앞쪽 원소의 그룹으로 합친다고 생각을 하겠습니다. 다음으로&amp;nbsp;Union&amp;nbsp;2,&amp;nbsp;3을&amp;nbsp;하면&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/68YKf/btsKtMXUkrM/jINWyvDy0ona0OvGUDngf1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/68YKf/btsKtMXUkrM/jINWyvDy0ona0OvGUDngf1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/68YKf/btsKtMXUkrM/jINWyvDy0ona0OvGUDngf1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F68YKf%2FbtsKtMXUkrM%2FjINWyvDy0ona0OvGUDngf1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1920&quot; height=&quot;1080&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;3번 원소의 그룹을 2로 바꾸면 됩니다. 그러면 여기서 질문으로 Union 연산의 시간복잡도는 얼마일까요? 지금까지 살펴본 내용만 보면 O(1)이 아닌가 하는 생각을 할 수도 있지만 여기서 Union 1, 3을 수행하려고 한다면 이전과 다른 상황이 발생한다는걸 확인할 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/b5gMxl/btsKue0JdCL/JxP3nsCreFzbJKP3RmeEQ1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/b5gMxl/btsKue0JdCL/JxP3nsCreFzbJKP3RmeEQ1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/b5gMxl/btsKue0JdCL/JxP3nsCreFzbJKP3RmeEQ1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fb5gMxl%2FbtsKue0JdCL%2FJxP3nsCreFzbJKP3RmeEQ1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1920&quot; height=&quot;1080&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Union 1, 3을 수행할 때 3번 원소의 그룹만을 1번으로 바꾸면 뭔가 좀 이상합니다. 아까 Union 2, 3으로 인해 2번과 3번 원소가 한 그룹이 되었기 때문에 이번에 Union 1, 3를 하고 나면 2번 원소의 그룹도 같이 바꿔줘야 합니다. 정리를 해보면 Union u, v 명령이 들어오면 u의 그룹을 확인하고, 전체 원소를 살펴보면서 v와 같은 그룹인 모든 원소들의 그룹을 u의 그룹으로 바꿔줘야 합니다. 그렇기 때문에 각 원소의 그룹을 배열로 관리하는 지금의 구현 방식에서 시간복잡도를 살펴보면 Find는 O(1), Union은 O(N)입니다. 반면 실제 Union-Find 자료구조에서는 두 연산 모두가 거의 상수 시간에 해결이 가능합니다. 과연 실제로는 어떤 방식으로 구현이 이루어져 있길래 그게 가능한건지 같이 알아보겠습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bLE082/btsKucBMK4G/7klCkMKneR9qLtHzFN2Eik/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bLE082/btsKucBMK4G/7klCkMKneR9qLtHzFN2Eik/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bLE082/btsKucBMK4G/7klCkMKneR9qLtHzFN2Eik/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbLE082%2FbtsKucBMK4G%2F7klCkMKneR9qLtHzFN2Eik%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1920&quot; height=&quot;1080&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;실제 구현에서는 각 원소를 정점으로 생각하고 그룹은 트리로 표현한 다음 Union 연산이 발생할 때 마다 한 트리의 루트가 다른 트리의 자식으로 들어가서 두 개의 트리가 합쳐집니다. Union 연산을 하는걸 한 번 보면 쉽게 무슨 뜻인지 이해할 수 있습니다. 그리고 이 트리 구조를 실제 코드로 저장할 때에는 각 원소에 대해 부모 정점의 번호를 담을 배열을 만들고 값을 적절하게 쓰면 됩니다. 일단 처음에는 모든&amp;nbsp;원소에&amp;nbsp;대해&amp;nbsp;부모&amp;nbsp;정점이&amp;nbsp;없다는&amp;nbsp;뜻으로&amp;nbsp;-1을&amp;nbsp;채워두고&amp;nbsp;Union&amp;nbsp;1,&amp;nbsp;5를&amp;nbsp;하면&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/qb4Tu/btsKuO1i5AI/NDhd4pRYwsOHmc0uUg0HE1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/qb4Tu/btsKuO1i5AI/NDhd4pRYwsOHmc0uUg0HE1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/qb4Tu/btsKuO1i5AI/NDhd4pRYwsOHmc0uUg0HE1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fqb4Tu%2FbtsKuO1i5AI%2FNDhd4pRYwsOHmc0uUg0HE1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1920&quot; height=&quot;1080&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;5번 정점을 1번 정점의 자식으로 만듭니다. 다음으로 Union 2, 3을 하면&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/ce4lZq/btsKulrPAL3/S3aHsHOfxMDYDyU4Cj1hN0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/ce4lZq/btsKulrPAL3/S3aHsHOfxMDYDyU4Cj1hN0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/ce4lZq/btsKulrPAL3/S3aHsHOfxMDYDyU4Cj1hN0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fce4lZq%2FbtsKulrPAL3%2FS3aHsHOfxMDYDyU4Cj1hN0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1920&quot; height=&quot;1080&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;자연스럽게 3번 정점을 2번 정점의 자식으로 만들면 되고,&amp;nbsp;여기서&amp;nbsp;Union&amp;nbsp;1,&amp;nbsp;3를&amp;nbsp;하면&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dajRQ6/btsKuvgLN7P/rPRhQgn5JZ4XZRSYqEiuVK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dajRQ6/btsKuvgLN7P/rPRhQgn5JZ4XZRSYqEiuVK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dajRQ6/btsKuvgLN7P/rPRhQgn5JZ4XZRSYqEiuVK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdajRQ6%2FbtsKuvgLN7P%2FrPRhQgn5JZ4XZRSYqEiuVK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1920&quot; height=&quot;1080&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그 전과는 다르게 3번 정점을 1번 정점의 자식으로 만들면 안됩니다. 그렇게 되면 2번 정점이 낙동강 오리알 신세가 되어버리기 때문에 3번 정점이 속한 그룹 전체가 1번 정점이 속한 그룹과 합쳐질 수 있도록 하려면 3번 정점이 속한 그룹의 루트인 2번 정점을 1번 정점의 자식으로 만들어야 합니다. 이렇게 2번 정점을 1번 정점의 자식으로 만들고 나면 1, 2, 3, 5가 같은 트리에 속하기 때문에 같은 그룹인게&amp;nbsp;눈에 바로 보입니다. 마지막으로 Union 2, 6을 해보겠습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bCed7C/btsKuyK9hiF/5n2sKvyjR0HPDUiNBu6cU0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bCed7C/btsKuyK9hiF/5n2sKvyjR0HPDUiNBu6cU0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bCed7C/btsKuyK9hiF/5n2sKvyjR0HPDUiNBu6cU0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbCed7C%2FbtsKuyK9hiF%2F5n2sKvyjR0HPDUiNBu6cU0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1920&quot; height=&quot;1080&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Union 2, 6을 할 때에는 6번 정점이 속한 그룹의 루트를 2번 정점이 속한 그룹의 자식으로 만들면 됩니다. 사실 6번 정점을 루트인 1번 정점 대신 그냥 2번 정점의 자식으로 둔다고 해도 문제가 있는건 아니지만 Union u, v를 할 때 u와 v 모두에 대해 루트를 확인하면 혹시 u와 v가 같은 그룹인지를 판단할 수 있습니다. 그렇기 때문에 v의 루트를 u의 자식으로 만드는게 아닌, v의 루트를 u의 루트의 자식으로 만든다고 생각하겠습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이렇게 Union을 살펴보았고 어떻게 동작하는지는 충분히 이해가 됐을거라고 생각하는데, 실제 구현 방식이랑 시간복잡도는 Find 연산까지 보고난 후에 같이 얘기를 나눠보겠습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/Sb0ue/btsKtS4Kbkm/HLpHurF8LshIVKQyuUkK40/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/Sb0ue/btsKtS4Kbkm/HLpHurF8LshIVKQyuUkK40/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/Sb0ue/btsKtS4Kbkm/HLpHurF8LshIVKQyuUkK40/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FSb0ue%2FbtsKtS4Kbkm%2FHLpHurF8LshIVKQyuUkK40%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1920&quot; height=&quot;1080&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Find 연산에서는 내가 속한 그룹의 번호를 알아내야 하는데, 다른 말로 표현하면 내가 속한 트리의 루트를 구하면 됩니다. 지금 상황에서 1, 2, 3, 5, 6번 원소의 그룹의 번호는 1이고, 4, 7, 8, 9, 10번 원소의 그룹의 번호는 자기 자신입니다. 그리고 이걸 구현할 때에는 루트에 도달할 때 까지 계속 부모 정점을 타고 올라가면 되는데, 3번 원소의 그룹을 찾는걸 한 번 보면 금방 이해가 될 수 있습니다. Find 3을 같이 해보겠습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bXyhMH/btsKtSKqvKZ/ELCkTPyP2kGIftcfziKIK1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bXyhMH/btsKtSKqvKZ/ELCkTPyP2kGIftcfziKIK1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bXyhMH/btsKtSKqvKZ/ELCkTPyP2kGIftcfziKIK1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbXyhMH%2FbtsKtSKqvKZ%2FELCkTPyP2kGIftcfziKIK1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1920&quot; height=&quot;1080&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Find 3을 하기 위해서 일단 3번 정점의 부모 정점을 확인합니다. 부모 정점이 2번이기 때문에 먼저 2번으로 올라가면 됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/87RLT/btsKtIH65Tt/6w9A3nHilM0Qa2ukoHGFwk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/87RLT/btsKtIH65Tt/6w9A3nHilM0Qa2ukoHGFwk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/87RLT/btsKtIH65Tt/6w9A3nHilM0Qa2ukoHGFwk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F87RLT%2FbtsKtIH65Tt%2F6w9A3nHilM0Qa2ukoHGFwk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1920&quot; height=&quot;1080&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2번 정점에 도착한 다음에는 마찬가지로 2번 정점의 부모 정점을 확인합니다. 부모 정점이 1번이기 때문에 1번으로 올라가면 됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/sjsPB/btsKvBNTIkm/oPfZ738PFKFkUvrtQ3SQt1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/sjsPB/btsKvBNTIkm/oPfZ738PFKFkUvrtQ3SQt1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/sjsPB/btsKvBNTIkm/oPfZ738PFKFkUvrtQ3SQt1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FsjsPB%2FbtsKvBNTIkm%2FoPfZ738PFKFkUvrtQ3SQt1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1920&quot; height=&quot;1080&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1번 정점에 도착한 다음에는 다시 1번 정점의 부모 정점을 확인하면 되는데, 1번 정점의 부모 정점은 -1로 기록이 되어있고 이 말은 곧 1번 정점이 루트임을 나타내기 때문에 여기서 올라가는걸 중단하고 3번 정점의 그룹 번호가 현재 정점의 번호인 1임을 알 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/oXodP/btsKt6BD4ag/K68ek8cEcbDuIR02bXVTTK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/oXodP/btsKt6BD4ag/K68ek8cEcbDuIR02bXVTTK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/oXodP/btsKt6BD4ag/K68ek8cEcbDuIR02bXVTTK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FoXodP%2FbtsKt6BD4ag%2FK68ek8cEcbDuIR02bXVTTK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1920&quot; height=&quot;1080&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;부모 정점이 저장된 배열을 p라고 할 때, 우선 find 연산부터 구현을 해보겠습니다. 다음 슬라이드에 코드가 바로 나오고 또 코드가 비교적 단순하긴 해서 굳이 직접 타이핑까지는 안해보셔도 되지만 한번 나라면 어떤식으로 구현을 할까 형태를 한 번 고민해보시는걸 추천드립니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/xJLqZ/btsKvaC180A/QGXrwmksdTORLD5iJnMCb1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/xJLqZ/btsKvaC180A/QGXrwmksdTORLD5iJnMCb1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/xJLqZ/btsKvaC180A/QGXrwmksdTORLD5iJnMCb1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FxJLqZ%2FbtsKvaC180A%2FQGXrwmksdTORLD5iJnMCb1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1920&quot; height=&quot;1080&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이렇게 코드는 그냥저냥 단순합니다. 반복문으로 작성해도 되지만 그냥 재귀로 짰는데, 지금 이 강의를 보고 계실 정도면 재귀가 그렇게 막 부담스럽지는 않겠죠?&amp;nbsp;p[x]가 음수이면 x가 루트라는 의미이니 x를 반환하고, 그렇지 않으면 find(p[x])를 반환하면 자연스럽게 부모로 한 단계씩 올라가면서 루트를 찾게 됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bEpL0a/btsKvpzYeru/KxzPNkZZQLt7TANmJsPJF1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bEpL0a/btsKvpzYeru/KxzPNkZZQLt7TANmJsPJF1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bEpL0a/btsKvpzYeru/KxzPNkZZQLt7TANmJsPJF1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbEpL0a%2FbtsKvpzYeru%2FKxzPNkZZQLt7TANmJsPJF1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1920&quot; height=&quot;1080&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다음으로는 Union을 구현해볼건데, 앞에서 Union u, v를 하던 과정을 다시 떠올려보면 u가 속한 트리의 루트를 찾고 v가 속한 트리의 루트를 찾은 후 v가 속한 트리의 루트를 u가 속한 트리의 루트의 자식으로 만들었습니다. 이걸 코드로 옮기면 되는데, Find와 마찬가지로 한 번 머릿속으로 고민해보고 나서 다음 슬라이드를 확인해봅시다. 그리고 함수 이름이 uni인 이유는 아쉽게도 union이 공용체를 의미하는 예약어여서 함수 이름으로 쓸 수 없어서 그런거고, 또 자료형이 bool인 이유는 만약 u와 v가 이미 같은 그룹이어서 Union을 할 필요가 없으면 false를, 다른 그룹이어서 Union이 정상적으로 이루어졌으면 true를 반환하고자 하는 목적입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/sgU1K/btsKvqr7qly/SdcHdl4x58HX6cF5j94bd0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/sgU1K/btsKvqr7qly/SdcHdl4x58HX6cF5j94bd0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/sgU1K/btsKvqr7qly/SdcHdl4x58HX6cF5j94bd0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FsgU1K%2FbtsKvqr7qly%2FSdcHdl4x58HX6cF5j94bd0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1920&quot; height=&quot;1080&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;여기 코드를 같이 확인해보면, 일단 u와 v 모두 find를 해서 루트의 번호를 u와 v에 대입시킵니다. 만약 두 개가 같다면 둘이 같은 그룹이라는 의미이기 때문에 false를 반환하면 되고, 그렇지 않다면 v의 부모를 u로 바꾼 후 true를 반환하면 됩니다. 크게 어려운건 없습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/Px4pp/btsKvfEknkZ/rZr7f2u1Pk5B81pwvc95kk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/Px4pp/btsKvfEknkZ/rZr7f2u1Pk5B81pwvc95kk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/Px4pp/btsKvfEknkZ/rZr7f2u1Pk5B81pwvc95kk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FPx4pp%2FbtsKvfEknkZ%2FrZr7f2u1Pk5B81pwvc95kk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1920&quot; height=&quot;1080&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이제 시간복잡도를 같이 생각해볼건데, Union의 경우에는 u, v 각각에 대해 find를 수행한 뒤에 12-15번째 줄에서 처리하는 일은 그냥 O(1)입니다. 그렇기 때문에 Find 함수의 실행 시간이 전체 시간복잡도를 따질 때 중요하게 작용합니다. 그리고 Find 함수는 부모를 타고 한 단계씩 올라가는 방식으로 구현이 되어 있기 때문에 각 정점에 대해 Find 함수를 적용할 경우 해당 정점의 깊이만큼의 시간이 필요합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/c0LVJj/btsKtqVfw7b/mfkxuQAYkFwXTsDGK2BpA0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/c0LVJj/btsKtqVfw7b/mfkxuQAYkFwXTsDGK2BpA0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/c0LVJj/btsKtqVfw7b/mfkxuQAYkFwXTsDGK2BpA0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fc0LVJj%2FbtsKtqVfw7b%2FmfkxuQAYkFwXTsDGK2BpA0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1920&quot; height=&quot;1080&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;문제는 최악의 경우 정점의 깊이가 최대 N이 될 수 있다는 점입니다. 예를 들어 Union 2, 1 / Union 3, 2 / Union 4, 3 / Union 5, 4 / Union 6, 5 이런식으로 Union을 적용한다면 이렇게 일자인 트리를 별로 어렵지 않게 만들 수 있고 이 상황에서 Find 1은 O(N)에 동작합니다. 이러면 처음의 직관적인 구현이 시간복잡도가 안 좋아서 트리를 이용해 Union-Find 자료구조를 만든게 아무 의미가 없게습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;사실 정식 Union-Find는 여기에다가 뒷 챕터에서 소개할 최적화를 추가로 적용해야 우리가 원하는 효율적인 자료구조로 쓸 수 있습니다. 만약 최적화를 적용하지 않게 되면 지금 본 것과 같이 Union과 Find 모두 최악의 경우 O(N)에 동작하는 비효율적인 구조가 된다는 점을 꼭 기억합시다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bnuMqD/btsKtqVfxkO/QD6V6c83hA54JPEnaLdjWk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bnuMqD/btsKtqVfxkO/QD6V6c83hA54JPEnaLdjWk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bnuMqD/btsKtqVfxkO/QD6V6c83hA54JPEnaLdjWk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbnuMqD%2FbtsKtqVfxkO%2FQD6V6c83hA54JPEnaLdjWk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1920&quot; height=&quot;1080&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Union-Find 자료구조에 적용할 수 있는 최적화는 2가지가 있는데, 첫 번째로 Union by rank를 알아보겠습니다. 만약 지금 슬라이드처럼 트리를 만들어 놓은 상태에서 Union 7, 2를 하고자 한다면 앞의 코드에서 p[v] = u로 작성한 것 처럼 7번 원소가 속해있는 트리의 루트는 1번, 2번 원소가 속해있는 트리의 루트는 2번이니 자연스럽게 1번 정점을 7번 정점의 자식으로 두게 됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/wQohq/btsKtLxWJU7/9WDQmnxWpMrK3izrT4G7Bk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/wQohq/btsKtLxWJU7/9WDQmnxWpMrK3izrT4G7Bk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/wQohq/btsKtLxWJU7/9WDQmnxWpMrK3izrT4G7Bk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FwQohq%2FbtsKtLxWJU7%2F9WDQmnxWpMrK3izrT4G7Bk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1920&quot; height=&quot;1080&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그런데 트리의 높이를 최대한 낮추는게 실행 시간 면에서 유리한데, 1번을 7번의 자식으로 두는 대신 7번을 1번의 자식으로 두면 전체적으로 트리의 높이를 더 낮게 유지할 수 있습니다. 즉 Union을 할 때 그냥 무조건 p[v] = u를 하는게 아니라, u가 속해있는 트리의 높이와 v가 속해있는 트리의 높이를 비교한 다음 더 낮은 트리를 높은 트리의 자식으로 붙이는 최적화를 할 수 있습니다. 그리고 이 높이를 랭크라고 부를 예정입니다. 그러면 왜 이 최적화의 이름이 Union by rank인지 이해를 할 수 있을거라고 생각합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Union by rank를 위해서는 각 그룹이 속해있는 트리의 랭크를 관리하고 있어야 하는데, rnk와 같은 별도의 배열을 둘 수도 있겠지만 제가 좋아하는 구현 방식은 부모 정점을 저장하는 p 배열 안에서 랭크도 같이 관리하는 방식입니다. 이전에는 p 배열에서 값이 양수이면 부모의 정점을 의미하고 값이 -1이면 해당 정점이 루트임을 의미했는데, 트리의 높이가 증가함에 따라 -1을 -2, -3, -4 이렇게 만들 예정입니다. 실제 Union을 하는 예시를 보면서 이해해보겠습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bxEa5f/btsKuu3igJC/KKPijH7Y3cHRvknCRmaWmk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bxEa5f/btsKuu3igJC/KKPijH7Y3cHRvknCRmaWmk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bxEa5f/btsKuu3igJC/KKPijH7Y3cHRvknCRmaWmk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbxEa5f%2FbtsKuu3igJC%2FKKPijH7Y3cHRvknCRmaWmk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1920&quot; height=&quot;1080&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;일단 처음 시작은 별반 다를거 없이 전체를 -1로 초기화해둡니다. -1의 의미는 해당 정점이 루트이고 또 트리의 높이가 1임을 의미합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bgy4Zq/btsKuHuArDa/ZKdxJ5FD56zFdLdXPiRhlK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bgy4Zq/btsKuHuArDa/ZKdxJ5FD56zFdLdXPiRhlK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bgy4Zq/btsKuHuArDa/ZKdxJ5FD56zFdLdXPiRhlK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fbgy4Zq%2FbtsKuHuArDa%2FZKdxJ5FD56zFdLdXPiRhlK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1920&quot; height=&quot;1080&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;여기서 Union 1, 5를 하면 1과 5 둘 다 트리의 높이는 1로 동일하니 1을 5의 자식으로 만들어도, 5를 1의 자식으로 만들어도 상관없습니다. 일단 5를 1의 자식으로 만들었다고 생각하겠습니다. 그렇게 되면 p[5]를 1로 변경하고, 그와 함께 p[1] 또한 -2로 변경합니다. p[1] = -2라는 것은 1이 루트인 트리의 높이가 2임을 나타냅니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/kwYnM/btsKtWTAA4u/Zd5OglKQwmcK7S2dper5L1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/kwYnM/btsKtWTAA4u/Zd5OglKQwmcK7S2dper5L1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/kwYnM/btsKtWTAA4u/Zd5OglKQwmcK7S2dper5L1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FkwYnM%2FbtsKtWTAA4u%2FZd5OglKQwmcK7S2dper5L1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1920&quot; height=&quot;1080&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다음으로 Union 2, 3을 비슷하게 p[3] = 2로 바꾸고, p[2]도 높이가 2가 되었다는 의미로 p[2] = -2로 변경합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bOUT8E/btsKveyEux4/B58vvkFKbKSXsnPJnodzH1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bOUT8E/btsKveyEux4/B58vvkFKbKSXsnPJnodzH1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bOUT8E/btsKveyEux4/B58vvkFKbKSXsnPJnodzH1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbOUT8E%2FbtsKveyEux4%2FB58vvkFKbKSXsnPJnodzH1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1920&quot; height=&quot;1080&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다음으로 Union 4, 3을 하려고 합니다. 그러면 먼저 Find 4를 해서 4가 속한 그룹의 루트가 4인걸 알아내고, 또 Find 3을 해서 3이 속한 그룹의 루트가 2인걸 알아냅니다. 그리고 2의 랭크와 4의 랭크를 비교하면 4의 랭크가 더 낮기 때문에 4를 2의 자식으로 만들어서 p[4] = 2로 바꾸면 됩니다. 또 랭크가 동일한 두 그룹을 합치면 높이가 1 늘어나니 랭크 또한 1 늘어나겠지만 지금처럼 랭크가 낮은 그룹을 높은 그룹에 합칠 때에는 트리의 높이가 그대로이기 때문에 랭크가 바뀌지 않습니다. 그래서 p[2]는 -2로 그대로 두면 됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/MzKeN/btsKvnvo1SH/c1LzhuJeHJpFfEIq9KXgWK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/MzKeN/btsKvnvo1SH/c1LzhuJeHJpFfEIq9KXgWK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/MzKeN/btsKvnvo1SH/c1LzhuJeHJpFfEIq9KXgWK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FMzKeN%2FbtsKvnvo1SH%2Fc1LzhuJeHJpFfEIq9KXgWK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1920&quot; height=&quot;1080&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;마지막으로 Union 1, 4를 하면 각각이 속한 그룹의 루트인 1, 2를 찾고 랭크를 비교하는데 랭크가 동일하니 둘 중 아무거나 선택해서 다른 하나의 자식으로 두면 됩니다. 2를 1의 자식으로 둔다고 하면 p[2] = 1로 바꾸고, 1의 랭크 또한 1 증가시켜서 p[1] = -3으로 바꾸면 됩니다. 이렇게 Union을 할 때 트리의 높이를 고려해서 합치는 최적화를 Union by rank라고 합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/btsLR2/btsKtV1krUg/rIL39Pr2qH6qOFalm4pvYK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/btsLR2/btsKtV1krUg/rIL39Pr2qH6qOFalm4pvYK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/btsLR2/btsKtV1krUg/rIL39Pr2qH6qOFalm4pvYK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbtsLR2%2FbtsKtV1krUg%2FrIL39Pr2qH6qOFalm4pvYK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1920&quot; height=&quot;1080&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이걸 코드로 옮겨보면 먼저 루트를 찾은 후 랭크에 따라 적절하게 처리를 하면 됩니다. p[u], p[v]에 랭크는 음수로 저장되어 있는걸 꼭 인지한 상태로 코드를 확인해봅시다. 예를 들어 p[v] &amp;lt; p[u]는 v의 랭크가 u보다 클 때 true이고, 또 u의 랭크를 1 증가시키는게 p[u]-- 입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/baVdPd/btsKuv2cKbF/xRxcklnMU2TLTyz6kFMqvk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/baVdPd/btsKuv2cKbF/xRxcklnMU2TLTyz6kFMqvk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/baVdPd/btsKuv2cKbF/xRxcklnMU2TLTyz6kFMqvk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbaVdPd%2FbtsKuv2cKbF%2FxRxcklnMU2TLTyz6kFMqvk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1920&quot; height=&quot;1080&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;두 번째 최적화 방법은 바로 경로압축으로, Find를 할 때 말 그대로 경로를 압축해 효율적으로 동작하게 만드는 방법입니다. Union-Find 자료구조에서 이런식으로 구조가 생겨있다고 해보겠습니다. 여기서 Find 3을 한다면 기존 Find에서는 3번 정점에서 출발해 부모를 따라 올라가며 루트인 6번 정점에 도달해서 그룹이 6번임을 확인한 후 끝내게 됩니다. 그런데 경로 압축에서는 6번 정점에 도달한 후 처리를 하나 더 하는데, 지나가는 길에 있던 모든 정점들을 전부 6번 정점의 자식으로 만듭니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/to5Vt/btsKtIOOmNs/EQLPyRXuFkoNrq1n7SCtF0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/to5Vt/btsKtIOOmNs/EQLPyRXuFkoNrq1n7SCtF0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/to5Vt/btsKtIOOmNs/EQLPyRXuFkoNrq1n7SCtF0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fto5Vt%2FbtsKtIOOmNs%2FEQLPyRXuFkoNrq1n7SCtF0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1920&quot; height=&quot;1080&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;즉, 지금 슬라이드처럼 Find 3을 하고 나면 3, 4번 정점이 6번 정점의 자식으로 옮겨갑니다. 이렇게 해도 여전히 3, 4번 정점은 6번 정점이 루트인 트리에 속해있으니 구조에 문제가 없고, 트리의 높이는 줄일 수 있습니다. 경로 압축은 간단한 아이디어이면서도 효과적입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/xzHsu/btsKuyqRS0u/CSwvNrKt3o2ieQDaZPHFwk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/xzHsu/btsKuyqRS0u/CSwvNrKt3o2ieQDaZPHFwk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/xzHsu/btsKuyqRS0u/CSwvNrKt3o2ieQDaZPHFwk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FxzHsu%2FbtsKuyqRS0u%2FCSwvNrKt3o2ieQDaZPHFwk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1920&quot; height=&quot;1080&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 최적화를 find 함수에 적용하려면 06번째 줄 처럼 기존에는 그냥 find(p[x])를 반환하던걸, p[x]에 대입까지 할 수 있게 p[x] = find(p[x])로 바꿔주면 끝입니다. 이렇게 하면 자연스럽게 루트까지 가는 경로 상으로 거치게 되는 각 x에 대해 부모, 즉 p[x]가 루트로 바뀌게 됩니다. 이렇게 최적화를 적용하고 나면 Union-Find 자료구조가 원하던대로 효율적으로 동작합니다. &lt;a href=&quot;https://github.com/encrypted-def/basic-algo-lecture/blob/master/Appendix%20D/union-find.cpp&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;(코드)&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/rMRlR/btsKuVsx59f/NeCmJ2HIm98yeN7UmBbQ4K/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/rMRlR/btsKuVsx59f/NeCmJ2HIm98yeN7UmBbQ4K/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/rMRlR/btsKuVsx59f/NeCmJ2HIm98yeN7UmBbQ4K/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FrMRlR%2FbtsKuVsx59f%2FNeCmJ2HIm98yeN7UmBbQ4K%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1920&quot; height=&quot;1080&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그래서 구체적인 시간복잡도가 얼마냐고 하면, 원소의 수가 N개라고 할 때 최적화 1만 적용을 한다면 트리의 높이가 최대 log N으로 제한되어서 각 연산의 시간복잡도가 O(log N)입니다. 그리고 최적화 2만 적용을 한다면 이 경우에는 Amortized O(log N)이 되는데, Amortized는 동적 배열 단원에서 처음 언급드렸지만 연산을 한 번 할 때에는 운이 나쁘면 O(N)이 걸릴 수도 있습니다. 예를 들어 트리가 일자로 생겨있는 상황에서 리프 원소를 잡고 Find를 한다면 O(N)이 걸립니다. 하지만 Find를 하고 나면 트리의 높이가 2로 낮아지기 때문에 또다시 Find를 한다면 그 때에는 O(1)입니다. 이런식으로 M번의 연산을 할 때 매번 연산의 시간복잡도는 O(N), O(1), 이렇게 다양할 수 있지만 전체 시간을 합쳐보면 O(MlogN)이 된다는 의미입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;흥미로운건 최적화 1과 최적화 2를 같이 적용했을 때인데, 둘을 같이 적용하면 지금까지 한 번도 등장한 적 없는 Amortized O(&amp;alpha;(N))이라는 시간복잡도가 나옵니다. 이 &amp;alpha;(N)은 정확히는 애커만 역함수라고 이름 붙은 함수인데, 저 함수가 무엇이고 왜 저런 시간복잡도를 가지는지는 너무 나간 얘기라 생략하겠습니다. 하나 알고가면 되는건, 저기 적어놓은 것 처럼 N이 무려 2^2^2^65536-3이하일 때 &amp;alpha;(N)이 4 이하이기 때문에 우리가 현실적으로 사용할 N의 범위에서는 사실상 상수 취급을 하면 된다는 점입니다. 그래서 Union-Find 자료구조에서 연산의 시간복잡도가 &quot;사실상&quot; 상수 시간이라고 강조를 했던 것입니다. 그리고 실제로 문제를 풀 때 코드를 짠다면, 최적화 2개를 다 적용하면 물론 가장 성능이 좋겠지만 Amortized O(log N)도 충분히 빠릅니다. 그렇기 때문에 최적화를 아예 적용하지 않으면 문제가 되겠지만, 둘 중에서 하나만 적용을 한다고 하면 그걸로 인해서 시간초과가 발생할 가능성은 거의 없다고 보시면 됩니다. 어쨌거나 강의에서 2가지 최적화를 모두 소개해드렸으니 뒤의 연습문제에서는 2가지 최적화를 모두 적용해서 예시 코드를 작성하겠지만 여러분들의 경우에는 굳이 그렇게 할 필요는 없습니다. 둘 중 하나만 적용해도 전혀 문제 없고, 또 아무래도 Union by rank보다는 경로 압축이 코드가 훨씬 더 간단하니 그냥 경로 압축만 적용을 하셔도 아무 상관 없습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bZUsHC/btsKtXkBgUw/djDYRSy8HdhQLW9M1yuSU0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bZUsHC/btsKtXkBgUw/djDYRSy8HdhQLW9M1yuSU0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bZUsHC/btsKtXkBgUw/djDYRSy8HdhQLW9M1yuSU0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbZUsHC%2FbtsKtXkBgUw%2FdjDYRSy8HdhQLW9M1yuSU0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1920&quot; height=&quot;1080&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이제 즐거운 연습 문제 풀이 시간입니다. 첫 번째 문제는 &lt;a href=&quot;https://www.acmicpc.net/problem/1717&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;BOJ 1717번: 집합의 표현&lt;/a&gt;인데 문제를 보면 그냥 대놓고 Union-Find를 써서 풀면 되는 문제이구나 하는게 감이 옵니다. 집합을 합친다는건 Union에 대응되고 두 원소가 같은 집합에 포함되어 있는지 확인하는 연산은 Find에 대응됩니다. 제가 앞에서 작성한 Union-Find 코드를 바탕으로 이 문제의 코드를 작성해봅시다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/wCJra/btsKuyj7mD7/hZTYlUy8LCfP5ZHodrz4L1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/wCJra/btsKuyj7mD7/hZTYlUy8LCfP5ZHodrz4L1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/wCJra/btsKuyj7mD7/hZTYlUy8LCfP5ZHodrz4L1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FwCJra%2FbtsKuyj7mD7%2FhZTYlUy8LCfP5ZHodrz4L1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1920&quot; height=&quot;1080&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://github.com/encrypted-def/basic-algo-lecture/blob/master/Appendix%20D/1717.cpp&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;코드&lt;/a&gt;에서 특별히 꼭 강조를 해야하는 부분은 따로 없어 보입니다. q = 0일 땐 union을 하고, q = 1일 땐 find(a)와 find(b)를 해서 각각의 루트를 찾고 일치하는지 확인하면 끝입니다. 지금의 코드는 최적화 1과 2를 모두 적용한 코드인데, 그냥 개인적으로 궁금해서 최적화 1만 적용해서 내보고, 다음으로 최적화 2만 적용해서 제출해봤습니다. 그런데 세 경우 모두 32ms로 실행 시간이 동일했습니다. 물론 이론적으로는 최적화 1과 2를 적용한게 제일 좋고, 또 실행 시간은 테스트케이스에 따라 차이가 있을 수 있지만, 아무튼 최적화를 1개만 적용한다고 해서 큰 문제가 안된다는걸 확인할 수 있습니다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bzQA7H/btsKujU3aPi/sqhfeLvPWrr29drWKZj43k/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bzQA7H/btsKujU3aPi/sqhfeLvPWrr29drWKZj43k/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bzQA7H/btsKujU3aPi/sqhfeLvPWrr29drWKZj43k/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbzQA7H%2FbtsKujU3aPi%2FsqhfeLvPWrr29drWKZj43k%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1920&quot; height=&quot;1080&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다음&amp;nbsp;문제는&amp;nbsp;&lt;a href=&quot;https://www.acmicpc.net/problem/7511&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;BOJ 7511번: 소셜 네트워킹 어플리케이션&lt;/a&gt;입니다. 지금 다루는게 Union-Find니까 당연히 Union-Find로 풀리겠지만, Union-Find 말고도 그 전에 배운 알고리즘으로도 풀리겠네 하는 생각을 하실 수 있다면 참 좋을텐데 혹시 감이 오실까요?&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 문제는 BFS로도 해결이 가능합니다. 미리 친구 관계가 주어진걸로 그래프를 다 만들어놓고 BFS를 한 번 돌리고 나면 그 뒤로 두 사람이 주어질 때 마다 서로 방문이 가능한지, 문제의 표현대로면 경로가 존재하는지를 판단할 수 있습니다. 어떻게 보면 BOJ 1717번: 집합의 표현 문제에서 q = 0인 쿼리를 먼저 앞에 모아서 보내고 다음으로 q = 1인 쿼리를 하나씩 처리하는, 이전 문제의 쉬운 버전이 지금 이 7511번 문제라고 생각할 수 있습니다. 다른 말로 표현하면 지금 7511번 문제는 Union-Find와 BFS 모두로 풀리는데, 만약 문제를 살짝 바꿔서 친구 관계가 주어지는거랑 경로가 존재하는지를 판단하는거랑 순서가 섞여서 주어진다면 BFS로는 해결이 안됩니다. 그래서 약간의 팁을 드리자면, 아무래도 여러분은 지금 막 배운 Union-Find 보다는 수도 없이 문제를 많이 풀어봤을 BFS가 더 친숙할 것입니다. 그래서 뭔가 문제를 접했을 때 혹시 BFS가 되나 하고 고민을 해보는 경우가 많을텐데, BFS로 풀릴듯 말듯한데 약간 미묘하게 해결이 안되는 지점이 있는 경우라면 그 문제를 사실은 Union-Find로 풀어야 하는 것일수도 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;설명이 길어졌는데, 다시 문제로 돌아오면 이 문제를 Union-Find로 어떻게 풀면 될지는 금방 감이 올 것입니다. 심지어 이전 문제의 하위호환이니까요. 직접 한 번 짜보시고 다음 슬라이드에서 코드를 확인해봅시다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/tthNY/btsKuvul6hW/5D3KxOlr7saUtpwfcE7cK0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/tthNY/btsKuvul6hW/5D3KxOlr7saUtpwfcE7cK0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/tthNY/btsKuvul6hW/5D3KxOlr7saUtpwfcE7cK0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FtthNY%2FbtsKuvul6hW%2F5D3KxOlr7saUtpwfcE7cK0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1920&quot; height=&quot;1080&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://github.com/encrypted-def/basic-algo-lecture/blob/master/Appendix%20D/7511.cpp&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;코드&lt;/a&gt;를 보면 find, uni는 똑같으니 생략하고, 문제 한글 설명 기준으로 처음에 테스트케이스의 수가 주어진다는 얘기가 빠져있긴 한데 이정도는 그 동안 문제를 풀어온 짬바로 적당히 넘어가고, 새로운 테스트 케이스가 시작할 때 마다 24번째 줄처럼 p를 초기화하는걸 꼭 신경써야 합니다. 그 뒤는 그냥 자연스러운 흐름이어서 설명은 생략하겠습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bgn70y/btsKt9rCf4q/qmXYrKVfkKtQYUadgwpZuk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bgn70y/btsKt9rCf4q/qmXYrKVfkKtQYUadgwpZuk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bgn70y/btsKt9rCf4q/qmXYrKVfkKtQYUadgwpZuk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fbgn70y%2FbtsKt9rCf4q%2FqmXYrKVfkKtQYUadgwpZuk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1920&quot; height=&quot;1080&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이번 강의에서는 Union-Find 자료구조를 배우고 관련 문제를 풀어봤습니다. 사실 코딩테스트 기준으로는 Union-Find가 꽤 어려운 편에 속하는 자료구조이지만 지금 이렇게 부록 D까지 보실 정도면 앞 부분의 내용들은 꽤 숙지가 된 상태이실테니 화룡점정을 이룬다는 느낌으로 제공해드릴 문제를 풀어보면서 Union-Find를 응용하면 어떤 문제들이 나올 수 있는지를 익혀보시는걸 추천드립니다. 그럼&amp;nbsp;고생하셨습니다.&lt;/p&gt;</description>
      <category>강좌/실전 알고리즘</category>
      <author>BaaaaaaaaaaaaaaaaaaaaaaarkingDog</author>
      <guid isPermaLink="true">https://baaaaaaaaaaaaaaaaaaaaaaarkingdog.tistory.com/1097</guid>
      <comments>https://baaaaaaaaaaaaaaaaaaaaaaarkingdog.tistory.com/1097#entry1097comment</comments>
      <pubDate>Sat, 2 Nov 2024 23:09:25 +0900</pubDate>
    </item>
    <item>
      <title>내가 누구? 하프 마라톤 &amp;quot;Finisher&amp;quot;</title>
      <link>https://baaaaaaaaaaaaaaaaaaaaaaarkingdog.tistory.com/1096</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;blob&quot; data-origin-width=&quot;1689&quot; data-origin-height=&quot;3000&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/b5kAkT/btsKcih2Xb7/KVAZ2xlgLtA2UJUCEMct70/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/b5kAkT/btsKcih2Xb7/KVAZ2xlgLtA2UJUCEMct70/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/b5kAkT/btsKcih2Xb7/KVAZ2xlgLtA2UJUCEMct70/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fb5kAkT%2FbtsKcih2Xb7%2FKVAZ2xlgLtA2UJUCEMct70%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1689&quot; height=&quot;3000&quot; data-filename=&quot;blob&quot; data-origin-width=&quot;1689&quot; data-origin-height=&quot;3000&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;edited_KakaoTalk_20241020_132545597_02.jpg&quot; data-origin-width=&quot;1689&quot; data-origin-height=&quot;3000&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bKPSNb/btsKdeF3Lha/HXQf924FsXRT1IjY1QZ2H0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bKPSNb/btsKdeF3Lha/HXQf924FsXRT1IjY1QZ2H0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bKPSNb/btsKdeF3Lha/HXQf924FsXRT1IjY1QZ2H0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbKPSNb%2FbtsKdeF3Lha%2FHXQf924FsXRT1IjY1QZ2H0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1689&quot; height=&quot;3000&quot; data-filename=&quot;edited_KakaoTalk_20241020_132545597_02.jpg&quot; data-origin-width=&quot;1689&quot; data-origin-height=&quot;3000&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1080&quot; data-origin-height=&quot;2640&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/QNGOW/btsKbIBVLgw/vq7t7n7JA5F70w5nd5uWh0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/QNGOW/btsKbIBVLgw/vq7t7n7JA5F70w5nd5uWh0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/QNGOW/btsKbIBVLgw/vq7t7n7JA5F70w5nd5uWh0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FQNGOW%2FbtsKbIBVLgw%2Fvq7t7n7JA5F70w5nd5uWh0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1080&quot; height=&quot;2640&quot; data-origin-width=&quot;1080&quot; data-origin-height=&quot;2640&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1080&quot; data-origin-height=&quot;2640&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/csS1lU/btsKbJm0Tjc/CaSkH4L1HILV1HkUlUAvf1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/csS1lU/btsKbJm0Tjc/CaSkH4L1HILV1HkUlUAvf1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/csS1lU/btsKbJm0Tjc/CaSkH4L1HILV1HkUlUAvf1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcsS1lU%2FbtsKbJm0Tjc%2FCaSkH4L1HILV1HkUlUAvf1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1080&quot; height=&quot;2640&quot; data-origin-width=&quot;1080&quot; data-origin-height=&quot;2640&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;하프 완주했습니다!!&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;올해 4월부터 시작해서 러닝 마일리지는 총 150km 쌓았고, 2달 전에 12km LSD / 그 후 3주 훈련소 갔다와서 한달 전에 16km LSD / 2주 전 21km LSD까지 한 다음 뛰었고 생각보다는 뛸만했어요&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;직전 21km LSD때는 630 페이스로 가다가 한 17km 지점부터는 퍼져서 걷뛰걷뛰했는데 이번에는 2:15 페이스메이커 계속 따라가다가 16km 지점부터 치고나갔고, 다행히 끝까지 퍼지지않고 잘 밀고나갔습니다&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;아직 마일리지도 충분히 쌓이지 않았고 또 대청호 코스가 업힐이 미친 수준이었으니 더 연습하고 다음에 코스 좋은 곳에서 하프 뛰면 2시간 안에 충분히 들 수 있을 것 같습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;내년 봄 하프 2시간 컷 게섯거라~&lt;/p&gt;</description>
      <category>일상/의식의 흐름</category>
      <author>BaaaaaaaaaaaaaaaaaaaaaaarkingDog</author>
      <guid isPermaLink="true">https://baaaaaaaaaaaaaaaaaaaaaaarkingdog.tistory.com/1096</guid>
      <comments>https://baaaaaaaaaaaaaaaaaaaaaaarkingdog.tistory.com/1096#entry1096comment</comments>
      <pubDate>Sun, 20 Oct 2024 21:36:40 +0900</pubDate>
    </item>
    <item>
      <title>!</title>
      <link>https://baaaaaaaaaaaaaaaaaaaaaaarkingdog.tistory.com/1094</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;어제 12시쯤 자서 자기전에 세탁기를 빨래가 6시간 후에 완료되게 예약해두고 아 내일 피곤하겠는데 라는 생각을 했습니다. 그런데 막상 오늘 5시 20분에 되게 깔끔하게 그냥 눈이 떠져서 이게 무슨 일이지 하면서 빵이랑 우유 먹으면서 새벽의 여유를 즐기고 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;3주 전 까지는 논문을 컨퍼런스에 내느라 좀 많이 바빴고 지금은 약간 한가한 타임입니다. 2주 전에는 목금토일에 제주도를 갔다왔습니다. 원래는 현충일을 껴서 가고 싶었는데 친구랑 일정을 조율하다보니 그 전 주에 가게 되었고, 평소에 등산을 하지는 않았지만 한라산을 한 번 가보고 싶었어서 금요일엔 한라산을 갔다왔습니다. 성판악-관음사 코스로 갔다왔는데, 한라산이 높이에 비해서는 그렇게 어려운 편은 아니라고 하던데 실제로 딱 할 수 있을만큼 힘들었습니다. 등산은 아예 초보여서 지레 겁을 먹었는데 둘 다 그래도 나름 젊고(!!) 운동을 꾸준히 하고 있어서 왕복 7시간 정도로 꽤 빠르게 갔다 왔습니다. 살짝 안개비오고 흐려서 온도도 등산하기에 그럭저럭 괜찮았지만 바닥이 미끄럽고 무엇보다 안개때문에 백록담을 못 본게 아쉬웠습니다. 언젠간 지리산 설악산도 도전,,!!&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1050&quot; data-origin-height=&quot;1400&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/Z9v9r/btsHSfnVF9t/NkKzxGX5tzwglvNate4Ivk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/Z9v9r/btsHSfnVF9t/NkKzxGX5tzwglvNate4Ivk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/Z9v9r/btsHSfnVF9t/NkKzxGX5tzwglvNate4Ivk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FZ9v9r%2FbtsHSfnVF9t%2FNkKzxGX5tzwglvNate4Ivk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1050&quot; height=&quot;1400&quot; data-origin-width=&quot;1050&quot; data-origin-height=&quot;1400&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;저번주에는 주말에 약속을 왕창 잡고 주로 대학교때 친구들을 만나서 열심히 놀았습니다. 거의 음식도 성인병돼지파티느낌으로 먹고 금밤 토밤 모두 새벽까지 pc방에서 있었습니다. 토밤에는 배그를 입문해봤는데, 역시 남들 다 할 때 했어야 했는데 뒤늦게 입문을 하려하니 진짜 진입장벽이 너무 높아서 한 4시간정도 했지만 제대로 된 게임을 할 수가 없었습니다. 같이 pc방에 갔던 친구랑은 대학교 1학년때 툭하면 pc방 가서 다음날 아침까지 같이 협곡에서 뛰어놀고 그랬는데 넘나 추억이네요. 이젠 한 새벽 3시만 되어도 피곤하니 슬픕니다. 늙기 싫다 ㄹㅇ&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;여하튼 2주동안 되게 잘 쉬었어서 이제 다시 다음 논문 거리 생각하면서 일상으로 복귀할 타이밍입니다. 음식도 다시 좀 깨끗하게 챙겨먹고 요새 러닝에도 재미를 붙여서 졸업 전엔 마라톤 풀코스를 한 번 뛰어보겠다고 다짐하고 주 2-3회 정도 러닝을 하고 있습니다. 이렇게 동네방네 소문내고 다녔으니 ㄹㅇ 해보겠습니다 ^~^&lt;/p&gt;</description>
      <category>일상/의식의 흐름</category>
      <author>BaaaaaaaaaaaaaaaaaaaaaaarkingDog</author>
      <guid isPermaLink="true">https://baaaaaaaaaaaaaaaaaaaaaaarkingdog.tistory.com/1094</guid>
      <comments>https://baaaaaaaaaaaaaaaaaaaaaaarkingdog.tistory.com/1094#entry1094comment</comments>
      <pubDate>Mon, 10 Jun 2024 06:24:51 +0900</pubDate>
    </item>
    <item>
      <title>[실전 알고리즘] 부록 C - 비트마스킹</title>
      <link>https://baaaaaaaaaaaaaaaaaaaaaaarkingdog.tistory.com/1093</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;figure data-ke-type=&quot;video&quot; data-ke-style=&quot;alignCenter&quot; data-video-host=&quot;youtube&quot; data-video-url=&quot;https://www.youtube.com/watch?v=gSLf6lMi7kw&quot; data-video-width=&quot;0&quot; data-video-height=&quot;0&quot; data-video-origin-width=&quot;0&quot; data-video-origin-height=&quot;0&quot; data-ke-mobilestyle=&quot;widthContent&quot; data-video-title=&quot;[바킹독의 실전 알고리즘] 부록 C - 비트마스킹&quot; data-video-thumbnail=&quot;&quot; data-original-url=&quot;&quot;&gt;&lt;iframe src=&quot;https://www.youtube.com/embed/gSLf6lMi7kw&quot; width=&quot;0&quot; height=&quot;0&quot; frameborder=&quot;&quot; allowfullscreen=&quot;true&quot;&gt;&lt;/iframe&gt;
&lt;figcaption style=&quot;display: none;&quot;&gt;&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/NcGcQ/btsGeL8WbdO/reWbkZTMYI6Q1K5JqusZr1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/NcGcQ/btsGeL8WbdO/reWbkZTMYI6Q1K5JqusZr1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/NcGcQ/btsGeL8WbdO/reWbkZTMYI6Q1K5JqusZr1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FNcGcQ%2FbtsGeL8WbdO%2FreWbkZTMYI6Q1K5JqusZr1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1920&quot; height=&quot;1080&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;네 반갑습니다. 이번 부록 C에서는 비트마스킹을 다뤄보겠습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/Fp0Eb/btsGeAmcDFl/7z4PjlAFFdd1bCbKQjG6dk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/Fp0Eb/btsGeAmcDFl/7z4PjlAFFdd1bCbKQjG6dk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/Fp0Eb/btsGeAmcDFl/7z4PjlAFFdd1bCbKQjG6dk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FFp0Eb%2FbtsGeAmcDFl%2F7z4PjlAFFdd1bCbKQjG6dk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1920&quot; height=&quot;1080&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이번 강의에서는 간단하게 비트 연산자들을 살펴보고 비트마스킹을 익힌 후에 문제를 같이 풀어볼 예정입니다. 이것도 다른 부록들처럼 그렇게 양이 많지도 않고 어렵지도 않아서 약간은 편안한 마음으로 들을 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/VX6Q6/btsGe7RtdV0/R0QGGPoks4EWAKln1pWGX0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/VX6Q6/btsGe7RtdV0/R0QGGPoks4EWAKln1pWGX0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/VX6Q6/btsGe7RtdV0/R0QGGPoks4EWAKln1pWGX0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FVX6Q6%2FbtsGe7RtdV0%2FR0QGGPoks4EWAKln1pWGX0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1920&quot; height=&quot;1080&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;일단 비트마스킹은 우리가 흔히 아는, 0과 1을 담고 있는 비트를 이용해서 연산을 효율적으로 하는 그런 방법을 말합니다. 자료구조라고 하기에는 너무 좀 거창한 것 같고 구현 기법 정도로 생각을 할 수 있습니다. 그래서 먼저 비트와 비트 연산자에 대해서 설명을 드리겠습니다. Drop the bit yeah&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dNctTH/btsGd6FTBBV/xbKLDjmzEdcYuqgv6Rsifk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dNctTH/btsGd6FTBBV/xbKLDjmzEdcYuqgv6Rsifk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dNctTH/btsGd6FTBBV/xbKLDjmzEdcYuqgv6Rsifk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdNctTH%2FbtsGd6FTBBV%2FxbKLDjmzEdcYuqgv6Rsifk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1920&quot; height=&quot;1080&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;일단 먼저 1비트짜리에서의 비트 연산을 보겠습니다. 비트 연산은 AND(&amp;amp;), OR(|), XOR(^), NOT(~)이 있고 각각의 계산 결과를 확인해보세요. AND는 둘 다 1이어야 결과가 1이고, OR은 둘 중 하나라도 1이면 결과가 1이고, XOR은 둘 중 하나는 0이고 다른 하나는 1이면 결과가 1입니다. 마지막으로 NOT은 그냥 비트를 반전시키는 연산입니다. 여기서 AND와 OR은 조건문을 쓸 때 &amp;amp;&amp;amp;와 ||으로 작성을 많이 했다보니 익숙할텐데 XOR와 NOT은 아마 처음 봤을수도 있을 것 같습니다. 특히 XOR의 경우에는 ^ 이 기호가 지수승을 나타낼 때에도 많이 사용합니다. 그래서&amp;nbsp;아직 프로그래밍에 안 익숙한 사람이 2의 3승같은거 계산하고 싶을 때 2^3으로 쓴다음에 이게 왜 8이 아니지 하는걸 종종 봤던 것 같은데 C++에서 ^는 지수가 아니라 XOR입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/J4PQW/btsGeyBUHEk/gs3y4P5fFc5wguRG9ZI3D0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/J4PQW/btsGeyBUHEk/gs3y4P5fFc5wguRG9ZI3D0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/J4PQW/btsGeyBUHEk/gs3y4P5fFc5wguRG9ZI3D0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FJ4PQW%2FbtsGeyBUHEk%2Fgs3y4P5fFc5wguRG9ZI3D0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1920&quot; height=&quot;1080&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다음으로 앞에서 본걸 char에서 해보겠습니다. int나 long long도 똑같습니다. 0x01강 &amp;ndash; 기초 코드 작성 요령 I에서 정수 자료형 관련해서 설명드린걸 잠깐 다시 봅시다. 이거 표 자체를 예전 ppt에서 그대로 가져온건데, 뭔가 4년 전의 저랑 지금의 저랑 미적 감각이 약간 다릅니다. 저때는 검정이랑 노랑이랑 섞으면 되게 명시성이 높다 해야하나 쨍하게 잘 보이니까 노랑 주황 이런걸 많이 썼는데 지금보니 좀 눈이 아픈 것 같기도 하고. 아무튼 char는 8개의 비트로 표현이 되는데 각 자리가 나타내는 값은 오른쪽부터 2^0, 2^1, .., 2^6, 그리고 제일 왼쪽에&amp;nbsp;-2^7이 있다는 그런 얘기를 했습니다. 그러면 9는 00001001로 표현이 가능합니다. 그리고 char에서 AND, OR, XOR, NOT과 같은 비트 연산을 한다고 치면 각 자리별로 그 연산을 수행을 하면 됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bMl0yv/btsGc7elFt3/tlZZDLDg4bKbnVKGN5drj0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bMl0yv/btsGc7elFt3/tlZZDLDg4bKbnVKGN5drj0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bMl0yv/btsGc7elFt3/tlZZDLDg4bKbnVKGN5drj0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbMl0yv%2FbtsGc7elFt3%2FtlZZDLDg4bKbnVKGN5drj0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1920&quot; height=&quot;1080&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그러니까 되게 간단한건데, 예를 들어서 9 &amp;amp; 14라고 하면 9는 비트로 표현했을 때 00001001이고 14는 00001110입니다. 그러면 각 자리별로 &amp;amp;를 수행을 하면 되고 오른쪽에서 4번째 비트, 즉 8에 대응되는 비트만 1이 되어서 9 &amp;amp; 14 = 8입니다. 나머지 예시들도 한 번 확인을 해보시면 될거고, 여기서 NOT이 살짝 신기한 성질을 가지고 있는데, signed 자료형에서는 ~x = -x &amp;ndash; 1입니다. 그러니까 ~16은 -17입니다. 이걸 어떤 관점에서 이해를 할 수가 있냐면 ~x와 x를 더했다 치면 각 비트가 다 1이 됩니다. x에서 0이었던 자리는 ~x에서 1이고 또 x에서 1이었던 자리는 ~x에서 0이기 때문에. 그리고 signed 자료형에서 11111111은 -1입니다. 그래서 ~x + x = -1이고 x를 넘기면 ~x = -x &amp;ndash; 1이라는 식이 나옵니다. 일단 상황은 이렇고, 그런데 저는 사실 NOT을 잘 안써서 한번씩 남의 코드에서 NOT이 나오면 순간 이거 계산 결과가 어떻게 되더라? 하고 머리를 굴리곤 합니다. 그래서 좀 헷갈린다 싶으면 NOT은 굳이 안쓰셔도 상관은 없습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/JMnqk/btsGcKqa5HB/5cmsRjwnFZ0dpxxzESsTn1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/JMnqk/btsGcKqa5HB/5cmsRjwnFZ0dpxxzESsTn1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/JMnqk/btsGcKqa5HB/5cmsRjwnFZ0dpxxzESsTn1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FJMnqk%2FbtsGcKqa5HB%2F5cmsRjwnFZ0dpxxzESsTn1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1920&quot; height=&quot;1080&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그리고 다음으로는 쉬프트 연산인데, Left shift는 비트를 전체적으로 왼쪽으로 미는 연산입니다. 그러면 한 칸씩 밀 때마다 자연스럽게 값이 2배가 됩니다. 참고로 이 성질을 시뮬레이션 단원에서 감시라는 문제를 풀 때 잘 써먹었습니다. 그래서 9를 한 칸 밀면 18이 되고 3을 세 칸 밀면 3에다가 2^3 = 8을 곱한거라 24가 됩니다. 반대로 Right shift는 비트를 전체적으로 오른쪽으로 밀고, 이 때 값은 한 칸 밀 때마다 2로 나눠진다고 생각하면 됩니다. 또 이 때 나머지는 자연스럽게 버려집니다. 그런데 쉬프트 연산을 할 때 overflow를 굉장히 잘 신경써야 합니다. 예를 들어서 char 1을 왼쪽으로 7칸 밀면 이건 10000000일텐데 그러면 1 &amp;lt;&amp;lt; 7 = -128인가? 혹은 1을 8칸을 밀면 1이 밀려나서 1 &amp;lt;&amp;lt; 8 = 0인가? 뭐 이런 생각이 듭니다. 그런데 이렇게 뭔가 논리적으로 생각을 하면 1 &amp;lt;&amp;lt; 7 = -128로 두고 1 &amp;lt;&amp;lt; 8 = 0으로 두는게 그렇게 막 말이 안되는 것 같지는 않은데, 이게 C++ 버전에 따라서 값이 달라지거나 아니면 아예 Undefined behavior라고 해서 어떤 값이 나올지 정해져있지 않은 그런 상황이 될 수가 있습니다. 그래서 규칙을 완전히 정확하게 다 이해할게 아니라면 쉬프트 연산은 무조건 0과 양수에 대해서만 쓰고 overflow가 일어나지 않도록 하게 쓰는게 좋습니다. 저도 규칙이 헷갈려서 그냥 쉬프트 연산은 0과 양수 범위 안에서만 쓰고 있습니다. 정리를 하면 left shift는 그냥 2를 곱하는 연산, right shift는 2를 나누고 나머지를 버리는 연산이다. 그리고 무조건 무 적 권 0과&amp;nbsp;양수&amp;nbsp;범위&amp;nbsp;안에서만&amp;nbsp;놀게&amp;nbsp;하자.&amp;nbsp;로&amp;nbsp;요약이&amp;nbsp;가능합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/qHErY/btsGeyaQqv2/zy0Kri92CAKzadmkkwqwNk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/qHErY/btsGeyaQqv2/zy0Kri92CAKzadmkkwqwNk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/qHErY/btsGeyaQqv2/zy0Kri92CAKzadmkkwqwNk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FqHErY%2FbtsGeyaQqv2%2Fzy0Kri92CAKzadmkkwqwNk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1920&quot; height=&quot;1080&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;그리고 유의할 점이 한 개 더 있는데, 바로 연산자 우선순위에 관한 상황입니다. 표에서 위에 있을수록 높은 우선순위이고, 주황색 글씨는 비트 연산자를 의미합니다. 보면 비트연산자 말고도 연산자가 꽤 다양하다보니 표도 꽤 양이 많은데, 비록 이렇게 표로 제시한건 처음이라도 이 우선순위는 우리가 자연스럽게 체화를 하고 있었습니다. 예를 들어 a는 1보다 크고 b는 3보다 크다라는 조건을 if문 안에 쓰고 싶으면 자연스럽게 if(a &amp;gt; 1 &amp;amp;&amp;amp; b &amp;gt; 3) 이라고 쓸 수 있는데, 논리 AND가 비교연산자 &amp;gt; 보다 우선순위가 높다는걸 알고 있기 때문에 굳이 a &amp;gt; 1과 b &amp;gt; 3에 괄호를 씌우지 않고 저렇게 표기를 해도 됐었습니다. 그런데 비트 연산자의 우선순위는 상대적으로 생소하고 이걸로 인해 코드가 의도한 것과 완전히 다르게 동작할 수 있습니다.&amp;nbsp; 예를 들어서 a &amp;lt;&amp;lt; 1과 b의 합을 계산하고 싶다면 무심코 a &amp;lt;&amp;lt;&amp;nbsp;&amp;nbsp;1 + b로 써버릴 수 있는데, 표에서 볼 수 있듯 더하기가 left shift보다 우선순위가 높아서 의도와 다르게 a를 1 + b칸만큼 왼쪽으로 밀어버리는 상황이 나옵니다. 그렇기 때문에 저렇게 괄호를 쓰셔야 합니다. 또 다른 예시를 보면, a와 b &amp;amp; c가 같은지를 if문 같은 곳에서 확인하고 싶다고 할 때 a == b &amp;amp; c라고 쓰면 의도와는 다르게 a == b가 먼저 실행됩니다. 그래서 같으면 1, 다르면 0이 먼저 계산되고 그 값이 c와 &amp;amp;로 계산되는, 아마 절대 의도하지 않았을 이상한 무언가가 됩니다. 그렇기 때문에 이 경우에도 괄호를 쳐야 합니다. 사실 우선순위 자체는 충분히 헷갈릴 수 있습니다. 저도 매번 헷갈립니다. 대신 뭘 명심하면 되냐면, 잘 모르겠으면 무조건 괄호를 다 치셔야 합니다. 특히 비트연산자가 들어가면 그냥 묻지도 따지지도 말고 괄호를 다 쳐버리는걸 추천드립니다.&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/vIhqQ/btsGcNfZX0M/XBxUcUNU9lAIP2kd2Wdbt0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/vIhqQ/btsGcNfZX0M/XBxUcUNU9lAIP2kd2Wdbt0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/vIhqQ/btsGcNfZX0M/XBxUcUNU9lAIP2kd2Wdbt0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FvIhqQ%2FbtsGcNfZX0M%2FXBxUcUNU9lAIP2kd2Wdbt0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1920&quot; height=&quot;1080&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이제 기초는 다 다졌고 비트마스킹을 이해하기 위한 준비가 끝났습니다. 일단 하나 알고가면 좋은건 비트마스킹은 시간복잡도를 빅오의 관점에서 줄여주지는 않습니다. 예를 들어서 정렬은 그냥 막 짜면 O(N^2)이지만 머지 소트나 퀵 소트를 이용하면 O(NlgN)이었습니다. 그런데 비트마스킹은 이렇게 뭔가 빅오의 관점에서 시간복잡도가 개선되는건 아닙니다. 하지만 그렇다고 해서 비트마스킹이 의미가 없는건 아닌게, 맨 처음에 설명을 할 때 비트마스킹이 구현 기법이라고 했었습니다. 비트 연산자랑 비트마스킹에 충분히 익숙하다는 가정 하에 비트마스킹을 쓰면 우선 구현을 좀 더&amp;nbsp;깔끔하게 할 수 있습니다. 안 익숙하면 비트마스킹을 짠 코드를 볼 때 이게 무슨 외계어인가 싶을 수 있지만 익숙해진 다음에 보면 원래는 추가 변수도 쓰고 조건문 식도 복잡해질 상황을 되게 깔끔하게 처리할 수가 있습니다. 두 번째로 실제 속도랑 메모리에서도 이점을 챙길 수 있습니다. 상황이 잘 맞아떨어지면 64배 가까이 성능이 향상될 수가 있습니다. 물론 보통 코딩테스트 수준에서는 비트마스킹을 꼭 써야만 시간 제한이나 메모리 제한을 맞출 수 있게 출제를 하지는 않습니다. 그렇긴 한데, 어찌됐든 내 코드가 빨리 돌면 나쁠건 없습니다. 혹시 운이 좋으면 원래는 통과되어서는 안될 시간복잡도를 가진 잘못된 풀이가 비트마스킹을 끼얹어서 통과될 수도 있기도 하니까요. 그래서 비트마스킹이 뭐냐면, 0과 1만을 상태로 가지는 여러 값들을 정수 한 개로 관리하는 기법을 말합니다. 조금 있다가 뒤의 연습 문제들을 보시면 바로 이해가 가긴 할텐데 일단 지금 간단한 예시로 설명을 한번 드려보겠습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/ED4zG/btsGd8jqiwo/mBaKdKeRwHHX4SWFxM4Qf1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/ED4zG/btsGd8jqiwo/mBaKdKeRwHHX4SWFxM4Qf1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/ED4zG/btsGd8jqiwo/mBaKdKeRwHHX4SWFxM4Qf1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FED4zG%2FbtsGd8jqiwo%2FmBaKdKeRwHHX4SWFxM4Qf1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1920&quot; height=&quot;1080&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;뭘 할거냐면 집합 {0, 1, 2, 3}의 모든 부분집합을 구해보려고 합니다. 이건 백트래킹이나 시뮬레이션 단원에서 많이 하던거랑 비슷합니다. 백트래킹으로 구현을 하면&amp;nbsp; 왼쪽처럼 짤 수가 있고 혹은 2진수 느낌으로 매번 2로 나누고 그 나머지를 가지고 처리하는 오른쪽 방법도 가능합니다. 지금 이 강의까지 오셨으면 두 방법 모두 충분히 익숙할거라고 생각해서 굳이 코드에 대한 설명은 하지 않겠습니다.&amp;nbsp; 그런데 여기서 오른쪽 방법은 결국 tmp 변수를 2진수로 나타냈을 때 각 비트가 0이면 해당 비트에 대응되는 수를 없다고 생각하고 1이면 수를 있다고 생각하는 방법입니다. 그러니까 tmp가 13이라면 이건 2진수로 나타냈을 때 1101인데, 제일 오른쪽에 있는 비트부터 차례대로 0, 1, 2, 3에 대응을 시킵니다. 그렇게 되면 13은 부분집합 {0, 2, 3}을 나타내게 됩니다. 이걸 오른쪽처럼 지금까지 짜왔고 저렇게 짠다고 해서 문제가 있는건 전혀 아니지만 비트 연산자를 잘 활용하면 더 간결하게 코드를 짤 수가 있어서&amp;nbsp;어떻게&amp;nbsp;한다는건지&amp;nbsp;한번&amp;nbsp;보겠습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bdAfPd/btsGdGgwfNP/InPELP1XsXQheYOu3MjOl1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bdAfPd/btsGdGgwfNP/InPELP1XsXQheYOu3MjOl1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bdAfPd/btsGdGgwfNP/InPELP1XsXQheYOu3MjOl1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbdAfPd%2FbtsGdGgwfNP%2FInPELP1XsXQheYOu3MjOl1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1920&quot; height=&quot;1080&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다시 상황을 정리하면 tmp가 주어졌을 때 각 비트가 0인지 1인지를 판단할 수 있어야 합니다. 이건 앞에서 봤던 비트 연산자 중에 &amp;amp;를 이용하면 확인이 가능합니다. 먼저 제일 오른쪽에 있는 비트가 1인지 아닌지를 판단하려면 tmp를 0001과 AND 연산을 해보면 됩니다. 그렇게 되면 연산의 결과에서 제일 오른쪽 비트를 제외한 다른 비트들은 무조건 0이고, 제일 오른쪽 비트의 값에 따라 연산의 결과가 정해집니다. 즉 최종적으로 AND 연산의 결과가 0이면 제일 오른쪽의 비트가 0이고, 0이 아니면 제일 오른쪽의 비트가 1입니다. 다음으로 오른쪽에서 2번째 비트를 구하려면 이번에는 0010과 AND를 계산해보면 됩니다. 이 결과가 0인지 아닌지를 가지고 오른쪽에서 2번째 비트가 0인지 1인지를 구분할 수 있습니다. 그리고 나머지 남은 비트들은 각각 0100, 1000과 AND를 계산해보면 된다는걸 쉽게 눈치챌 수 있을 것입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/kQEMA/btsGcLJf4zX/CkIK2TwDCgbGPs1SZVj7D0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/kQEMA/btsGcLJf4zX/CkIK2TwDCgbGPs1SZVj7D0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/kQEMA/btsGcLJf4zX/CkIK2TwDCgbGPs1SZVj7D0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FkQEMA%2FbtsGcLJf4zX%2FCkIK2TwDCgbGPs1SZVj7D0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1920&quot; height=&quot;1080&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 방법대로 구현을 하려면 0001, 0010, 0100, 1000을 계산해야 하는데 이건 left shift를 이용하면 됩니다. 1을 각각 0, 1, 2, 3칸 밀면 저 수들을 만들 수 있습니다. 최종적으로 코드를 짜보면 여기 func3처럼 구현이 가능합니다. 이전에 많이 했던, 수를 2로 나누고 나머지를 챙기는 방식으로 구현했던 func2와 비교를 해보면 직접 수를 나눌 필요가 없기 때문에 코드가 더 간결하고 또 func2에서의 brute와 같은 추가적인 변수가 필요없습니다. 물론 이 문제의 상황에서는 비트마스킹을 쓰지 않는다고 해서 크게 효율이 달라지지는 않기 때문에 만약 비트마스킹이 아직 익숙하지 않다면 비트마스킹을 이용해 이렇게 구현을 할 수 있다는 것만 확인하시고 계속 func2와 같은 방법으로 구현을 하셔도 상관은 없습니다. 하지만 뒤에서 같이 살펴볼 문제들은 비트마스킹을 활용했을 때의 이점이 있는 경우가 분명하게 있습니다.&amp;nbsp;이제&amp;nbsp;문제들을&amp;nbsp;같이&amp;nbsp;확인해보겠습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bkCWdC/btsGe9PfYqQ/BoDUaQ8PyUJrGTtgMswKF0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bkCWdC/btsGe9PfYqQ/BoDUaQ8PyUJrGTtgMswKF0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bkCWdC/btsGe9PfYqQ/BoDUaQ8PyUJrGTtgMswKF0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbkCWdC%2FbtsGe9PfYqQ%2FBoDUaQ8PyUJrGTtgMswKF0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1920&quot; height=&quot;1080&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이제 즐거운 문제 풀이 시간입니다. 첫 번째 문제는 &lt;a href=&quot;https://www.acmicpc.net/problem/11723&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;BOJ 11723번 집합&lt;/a&gt;인데, 풀이가 아마 직관적으로 보입니다. 그냥 1부터 20까지의 각 값이 S 안에 있는지 여부를 저장할 20칸짜리 배열을 하나 잡고 연산들에 따라서 그걸 1 혹은 0으로&amp;nbsp;적절하게 바꾸면 됩니다. 메모리 제한이 4MB로 굉장히 작긴 하지만 이 방법을 쓰면 어차피 int 배열 20칸만 쓰는거니 크게 문제가 없습니다. 먼저 이렇게 구현을 해보겠습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bvlrUn/btsGfJW01wR/k9ApgaSiucHkcXeeWG3wRk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bvlrUn/btsGfJW01wR/k9ApgaSiucHkcXeeWG3wRk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bvlrUn/btsGfJW01wR/k9ApgaSiucHkcXeeWG3wRk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbvlrUn%2FbtsGfJW01wR%2Fk9ApgaSiucHkcXeeWG3wRk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1920&quot; height=&quot;1080&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;제 &lt;a href=&quot;https://github.com/encrypted-def/basic-algo-lecture/blob/master/Appendix%20C/11723_1.cpp&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;구현코드&lt;/a&gt;이고 크게 특별한건 없습니다. 뭐 생소할수도 있는 부분은 toggle에서 0이면 1로, 1이면 0으로 바꾸는걸 if문을 쓰는 대신 xor로 했다 정도? 다들 비슷하게 구현을 했을거라고 생각합니다. 그런데 물론 이 코드도 통과를 하긴 하는데 비트마스킹을 이용하면 더 개선을 할 수가 있거든요. 먼저 결국 state 배열의 각 칸은 딱 1비트만 차지하는데 그걸 위해서 4바이트씩 주는게 아깝다고 생각이 되니까 이걸 그냥 20비트짜리 수 하나만으로 상태를 나타내보자 하는 생각을 할 수 있습니다. 그런데 뭐 이 문제가 특별히 메모리를 엄청 적게 줘서 그렇지 보통 메모리는 차고 넘치니까 int 20개를 1개로 바꾸는게 엄청 큰 의미가 있지는 않아보입니다. 하지만 비트마스킹을 쓰면서 생기는 두 번째 장점은 아주 큰데, all과 empty 명령을 생각해보겠습니다. 지금 상황에서는 제가 작성한 코드처럼 그냥 20칸을 다 돌면서 1 혹은 0으로 바꾸는 방법이 최선입니다. 그런데 int 1개로 상태를 나타내면 all&amp;nbsp;명령은&amp;nbsp;상태를&amp;nbsp;2진수로&amp;nbsp;111...11,&amp;nbsp;즉&amp;nbsp;0xFFFFF로&amp;nbsp;변경하면&amp;nbsp;되고&amp;nbsp;empty&amp;nbsp;명령은 &lt;br /&gt;상태를 0으로 만들면 바로 끝입니다. 이렇게 되면 20번 대입 연산을 하던걸 딱 1번의 대입 연산으로 해결할 수 있습니다. 즉 all과 empty 명령을 20배 더 빠르게 할 수 있게됩니다. 그래서 state를 배열이 아니라 int 1개로 두고 각 비트에 적절하게 비트연산을 수행해서 문제를 푸는 비트마스킹 기법으로 코드를 짜보겠습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bFXPzg/btsGeKCc82C/FZfce23VPoX99SPKogvVl1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bFXPzg/btsGeKCc82C/FZfce23VPoX99SPKogvVl1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bFXPzg/btsGeKCc82C/FZfce23VPoX99SPKogvVl1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbFXPzg%2FbtsGeKCc82C%2FFZfce23VPoX99SPKogvVl1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1920&quot; height=&quot;1080&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;일단 state가 int 1개로 바뀌고 각 명령들을 처리하는 방법도 달라졌는데, 하나씩 같이 살펴보겠습니다. 먼저 add를 보면 1 &amp;lt;&amp;lt; (x-1)을 OR을 해주면 자연스럽게 해당 비트가 켜집니다. 다음으로 remove는 약간 복잡한데, 어떻게 생각을 하면 되냐면 만약 제일 오른쪽 비트만 끄고 나머지는 그대로 유지를 하고 싶다면 11111..110과 AND를 하면 됩니다. 그러면 나머지 다른 모든 비트는 원래 자기 자신의 값을 그대로 가지는데 제일 오른쪽 비트는 0이 됩니다. 그리고 제일 오른쪽에서 두 번째 비트만 끄고 싶으면 11111..101과 AND를 하면 돼요. 그럼 이 때 111111..110 혹은 11111..101과 같은 값을 만들려고 1 &amp;lt;&amp;lt; (x-1)의 NOT을 계산합니다. 그래서 최종적으로 ~(1 &amp;lt;&amp;lt; (x-1))과 AND를 계산하면 오른쪽에서 x-1번째 비트를 끌 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다음으로 check인데, 부분집합을 출력하는 문제에서는 AND를 계산하는 값을 각 비트에 따라 0001, 0010, 0100, 1000 이렇게 왼쪽으로 밀었는데 지금은 출력이 0 혹은 1로 되어야 해서 state를 오른쪽으로 밀고 1과 AND를 계산하게 했습니다. toggle은 1 &amp;lt;&amp;lt; (x-1)과 XOR을 하면 되고, 마지막으로 all과 empty는 각각 state를 0xfffff와 0으로 업데이트를 하면 됩니다. 이렇게 int 1개만 써서 state를 표현하고, 비트마스킹으로 적절하게 처리가 가능합니다. 다만 실제 실행 시간은 앞의 풀이와 지금 풀이가 크게 차이가 없는걸 확인할 수 있는데,&amp;nbsp;입출력 양이 많아서 실행 시간의 대부분이 입출력 처리에 쓰여서 그렇습니다. &lt;a href=&quot;https://github.com/encrypted-def/basic-algo-lecture/blob/master/Appendix%20C/11723_2.cpp&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;(코드)&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/b0q9Hs/btsGcLikd9I/LdkHCyCEiyiMsqkkSADrC0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/b0q9Hs/btsGcLikd9I/LdkHCyCEiyiMsqkkSADrC0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/b0q9Hs/btsGcLikd9I/LdkHCyCEiyiMsqkkSADrC0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fb0q9Hs%2FbtsGcLikd9I%2FLdkHCyCEiyiMsqkkSADrC0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1920&quot; height=&quot;1080&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;두 번째 문제도 한 번 확인해봅시다. &lt;a href=&quot;https://www.acmicpc.net/problem/1497&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;(링크)&lt;/a&gt; 일단 비트마스킹에 연연하지 말고 풀이를 한다고 하면 되게 간단하게 해결이 가능합니다. 2^N개의 각 가능한 기타 조합에 대해서 해당 조합이 몇 개의 곡을 연주할 수 있는지를 확인하면 끝입니다. 즉 문제를 부분 문제로 나눠보면 2^N개의 기타 조합 만들기,&amp;nbsp;&amp;nbsp;조합이 몇 개의 곡을 연주할 수 있는지 확인하기 이렇게이고, 각각이 모두 비트마스킹을 이용해서 최적화를 할 수 있습니다. 2^N개의 기타 조합을 만드는건 앞에서 이미 같이 본거니까 생략하고 조합이 몇 개의 곡을 연주할 수 있는지를 어떻게 처리할지 고민해보겠습니다. 먼저 기타가 연주할 수 있는 곡의 목록이 YYYNN과 같은 방식으로 주어지는데, 이걸 string으로 저장하지 말고 앞의 문제에서 state와 같이 정수 하나에 넣습니다. 문제의 제한조건 상으로 M이 최대 50이니 32비트인 int에는 다 담을 수가 없고 대신 long long을 쓰면 됩니다. 즉 YYYNN은 이진수 11100으로 만들어서 곡의 목록을 11100 = 28으로 저장합니다. 그리고 내가 선택한 기타 조합이 몇 개의 곡을 연주할 수 있는지는 이 state들을 가지고 어떤 적절한 비트연산자를 적용하면 되는데, 딱 하나의 기타만이라도 1이면 그 곡을 연주할 수 있는거니까 이건 OR입니다. 즉 state들을 다 OR을 한 결과에 있는 1의 개수가 바로 조합이 연주할 수 있는 곡의 개수입니다. 이제 구현을 직접 해보겠습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/qQ8kP/btsGSMngD93/OnAkOe8M19fSS3QrxluoZk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/qQ8kP/btsGSMngD93/OnAkOe8M19fSS3QrxluoZk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/qQ8kP/btsGSMngD93/OnAkOe8M19fSS3QrxluoZk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FqQ8kP%2FbtsGSMngD93%2FOnAkOe8M19fSS3QrxluoZk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1920&quot; height=&quot;1080&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;일단 저는 bit_cnt라고 하는, long long 인자가 주어지면 거기에 있는 1의 개수를 반환해주는 함수를 하나 만들었습니다. 그리고 state[i]는 i번째 기타가 연주할 수 있는 곡의 정보를 정수 하나로 나타낸 값인데, 앞에서 설명했듯이 곡이 최대&amp;nbsp;50개여서 반드시 long long으로 선언을 해야합니다. 그리고 21번째 줄에서 저렇게 YYYNN 이런 입력받은 값을 가지고 state[i]를 구성할 때 state[i]를 left shift로 왼쪽으로 한 칸씩 밀면서 OR을 하는건 되게 많이 쓰이는 방법이라 눈에 한 번 익혀갑시다. 25번째 줄은 2^N가지 조합을 다 돌리기 위한 for문이고 28-30번째 줄처럼 비트가 켜져있는 기타들에 대해 state를 전부 OR 연산을 해줍니다. 최종적으로 그렇게 구해진 comb 변수에 있는 1의 개수를 구해서 적절하게 처리를 하면 끝입니다. 한 가지 실수하기 쉬운 점은 28번째 줄에서 (1LL &amp;lt;&amp;lt; i) 부분인데, tmp의 i번째 비트가 켜져있는지를 확인하기 위해 1 &amp;lt;&amp;lt; i를 계산하면 됩니다. 그런데 그냥 1은 int이고, 이걸 32칸 이상 왼쪽으로 밀면 오버플로우가 납니다. 차라리 컴파일이 안되면 빨리 알아차릴 수가 있는데, 실행은 잘 되지만 정작 결과가 이상해지고 심지어 곡이 32개 이상 있어야 오류를 발생하니 하필 예제는 다 잘 통과되어서 오류를 찾는데 꽤 오랜 시간이 걸리게 됩니다. 아무튼 left shift를 최대 50까지 해야하기 때문에 1을 long long으로 바꿔야 하고 그래서 (1LL &amp;lt;&amp;lt; i)로 코드를 짜야 합니다. &lt;a href=&quot;https://github.com/encrypted-def/basic-algo-lecture/blob/master/Appendix%20C/1497.cpp&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;(코드)&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/Ph6xO/btsGfMzrpZu/bPf02kZlXsAtwokqsKhW7K/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/Ph6xO/btsGfMzrpZu/bPf02kZlXsAtwokqsKhW7K/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/Ph6xO/btsGfMzrpZu/bPf02kZlXsAtwokqsKhW7K/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FPh6xO%2FbtsGfMzrpZu%2FbPf02kZlXsAtwokqsKhW7K%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1920&quot; height=&quot;1080&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;네 이번시간에는 이렇게 비트마스킹을 같이 살펴봤습니다. 비트 연산자에 익숙하다는 가정 하에 비트마스킹은 메모리와 성능 모두에 이득을 줄 수 있어서 구현 기법 중 하나로 익혀두면 분명 도움이 되는 순간이 있을 것입니다. 다만 보통 비트마스킹을 꼭 써야만 시간 혹은 메모리 제한을 맞출 수 있는 경우는 잘 없어서 나는 도저히 이 비트 연산자들이 낯설고 정이 안간다라고 하면 뭐 굳이 안하셔도 상관은 없습니다. 강의를 만든 제 입장에서는 아쉽긴 하지만. 본인이 종사하고자 하는 분야가 로우 레벨 쪽이면 꼭 비트미스킹이 아니더라도 비트 연산자를 볼 일이 많을거라 이번 기회에 겸사겸사 비트 연산자와 친해져보시고, 나는 로우 레벨은 아니다 하면 그래도 이게 그렇게 막 어려운건 아니니까 한 번 익혀보시면 좋겠지만 도저히 비트 연산자를 쓰기 싫다라고 하면 그냥 시뮬레이션 단원 느낌으로 문제들만 가볍게 한 번 풀어보시고 넘어가셔도 괜찮습니다. 그럼&amp;nbsp;고생&amp;nbsp;많으셨습니다.&amp;nbsp;안녕~&lt;/p&gt;</description>
      <category>강좌/실전 알고리즘</category>
      <author>BaaaaaaaaaaaaaaaaaaaaaaarkingDog</author>
      <guid isPermaLink="true">https://baaaaaaaaaaaaaaaaaaaaaaarkingdog.tistory.com/1093</guid>
      <comments>https://baaaaaaaaaaaaaaaaaaaaaaarkingdog.tistory.com/1093#entry1093comment</comments>
      <pubDate>Sun, 31 Mar 2024 01:35:44 +0900</pubDate>
    </item>
    <item>
      <title>사는 얘기</title>
      <link>https://baaaaaaaaaaaaaaaaaaaaaaarkingdog.tistory.com/1092</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;#1&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;크로스핏 오픈이 끝났습니다 &lt;a href=&quot;https://games.crossfit.com/athlete/2638378&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://games.crossfit.com/athlete/2638378&lt;/a&gt; 오픈 와드를 하면서 느낀게 근력이 많이 부족하다는 점이었습니다. 50 덤벨스내치는 아예 처음 해봤고, 185 데드랑 95 쓰러스터도 너무 힘들었습니다. 그래도 작년엔 23.3처럼 스내치 무게 때문에 아예 수행이 불가능한 오픈 와드도 있었는데 올해는 어찌됐든 다 수행을 할 수는 있었으니 나름 발전..했네요. 내년엔 한 상위 60% 정도에 들 수 있으면 좋겠습니당&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;운동을 계속 꾸준하게 하고 있는데 최근 8개월 동안 몸 상태랑 수행능력이 다 거의 제자리걸음을 하고 있어서 뭐가 문제일까 고민이 좀 많았습니다. 혹시 먹는 양이 부족한게 아닌가 싶어서 한 2주 전부터 진짜 작정하고 음식을 클린 푸드 위주로 계속 신경써서 많이 챙겨먹고 있습니다. 운동도 계속 열심히 하고 있으니 몸이 좋아지면 좋겠네요&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;#2&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;3월에 들어서 7시 출근 -&amp;gt; 4시 퇴근 -&amp;gt; 4시 반 크로스핏으로 살고 있습니다. 이게 규칙으로 정해진건 아니니 상황에 따라 너무 피곤해서 더 자면 약간 더 늦게 출근하고 일찍 깨면 더 일찍 가고 그러긴 하지만 전반적으로 잘 지키고 있는데, 그러다보니 자연스럽게 일찍 자서 엄청 힘들지는 않지만 세상 재밌는 일은 다 밤에 일어난다는 단점이 있긴 하네요.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;#3&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;저번주에 인스타 계정을 처음으로 만들었습니다. 처음에는 주변에 팔로우 해달라고 알리고 다니고 친구들 피드도 보면서 시간을 잘 때웠는데 막상 인스타를 하다보니 좀 뭐랄까.. 괜히 나를 어떻게 더 멋있게(그러면서 허세는 안느껴지게) 드러낼 수 있을까 고민하게 되고 내가 올린 거에 대한 반응이 신경쓰이고 또 굳이 모르고 사는게 더 나을 것들을 괜히 찾아보고 뭐 그런 것들이 제 정신 건강에 좋지 않다는 생각이 들어서 그냥 어플을 다시 지웠습니다. 솔직히 그냥 계정을 없애고 싶은데 가입했다고 동네방네 알리고나서 일주일만에 바로 탈퇴를 하면 너무 이상하게 보일까봐 그러지는 못하구,,, 대학원 진학하고 나서부터는 그냥 좀 있는듯 없는듯 지내는걸 좋아하고 애매하게 아는 사람들한테 굳이 내가 뭐하고 사는지 드러내고 싶지 않고 뭐 그런게 좀 있어요. 근데 정작 그러면서 블로그도 하고 유튜브에 브이로그는 올린건 뭐냐고 한다면 그건 보는 사람들이 애매하게 아는 사람들이 아니라 아예 모르는 사람이니까...?  &lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;#4&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;봄을 맞이해서 탈색을 했습니다. 좀 많이 튀긴 하지만 하고 나니 전반적인 톤이 밝아져서 매우 만족합니다. 18년에도 탈색을 했고 그 상태로 icpc scpc 뭐 기타 등등 각종 대회를 열심히 돌아다녔는데 18시즌에 저랑 접점이 있으셨던 분들 중에 이 블로그를 보실 분들이 아직 있을지 궁금하네요.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;723&quot; data-origin-height=&quot;1286&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/kKALV/btsFUIj0UuB/w9uKTqkOX039moDJBa9kuk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/kKALV/btsFUIj0UuB/w9uKTqkOX039moDJBa9kuk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/kKALV/btsFUIj0UuB/w9uKTqkOX039moDJBa9kuk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FkKALV%2FbtsFUIj0UuB%2Fw9uKTqkOX039moDJBa9kuk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;199&quot; height=&quot;354&quot; data-origin-width=&quot;723&quot; data-origin-height=&quot;1286&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;</description>
      <category>일상/의식의 흐름</category>
      <author>BaaaaaaaaaaaaaaaaaaaaaaarkingDog</author>
      <guid isPermaLink="true">https://baaaaaaaaaaaaaaaaaaaaaaarkingdog.tistory.com/1092</guid>
      <comments>https://baaaaaaaaaaaaaaaaaaaaaaarkingdog.tistory.com/1092#entry1092comment</comments>
      <pubDate>Mon, 18 Mar 2024 22:39:41 +0900</pubDate>
    </item>
    <item>
      <title>개취 띵곡</title>
      <link>https://baaaaaaaaaaaaaaaaaaaaaaarkingdog.tistory.com/1091</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;figure data-ke-type=&quot;video&quot; data-ke-style=&quot;alignCenter&quot; data-video-host=&quot;youtube&quot; data-video-url=&quot;https://www.youtube.com/watch?v=lCgzUiQt40I&quot; data-video-thumbnail=&quot;https://scrap.kakaocdn.net/dn/bKE5gY/hyVcazQVhK/VGlV7fGiZe1tpMbQMqoOWK/img.jpg?width=1280&amp;amp;height=720&amp;amp;face=0_0_1280_720&quot; data-video-width=&quot;860&quot; data-video-height=&quot;484&quot; data-video-origin-width=&quot;860&quot; data-video-origin-height=&quot;484&quot; data-ke-mobilestyle=&quot;widthContent&quot; data-video-title=&quot;반비례 (反比例) (反比例)&quot; data-original-url=&quot;&quot;&gt;&lt;iframe src=&quot;https://www.youtube.com/embed/lCgzUiQt40I&quot; width=&quot;860&quot; height=&quot;484&quot; frameborder=&quot;&quot; allowfullscreen=&quot;true&quot;&gt;&lt;/iframe&gt;
&lt;figcaption style=&quot;display: none;&quot;&gt;&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;figure data-ke-type=&quot;video&quot; data-ke-style=&quot;alignCenter&quot; data-video-host=&quot;youtube&quot; data-video-url=&quot;https://www.youtube.com/watch?v=4D_jASaNDSQ&quot; data-video-thumbnail=&quot;https://scrap.kakaocdn.net/dn/bnu99Z/hyVcaT91V5/LOisdKLDkgeF20xWsAsYSk/img.jpg?width=1280&amp;amp;height=720&amp;amp;face=0_0_1280_720&quot; data-video-width=&quot;860&quot; data-video-height=&quot;484&quot; data-video-origin-width=&quot;860&quot; data-video-origin-height=&quot;484&quot; data-ke-mobilestyle=&quot;widthContent&quot; data-video-title=&quot;[Official Audio] Miiro (미로) - 계절범죄 (Feat. 새빛)&quot; data-original-url=&quot;&quot;&gt;&lt;iframe src=&quot;https://www.youtube.com/embed/4D_jASaNDSQ&quot; width=&quot;860&quot; height=&quot;484&quot; frameborder=&quot;&quot; allowfullscreen=&quot;true&quot;&gt;&lt;/iframe&gt;
&lt;figcaption style=&quot;display: none;&quot;&gt;&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;비슷한 노래 알고 계시면 추천점,,&lt;/p&gt;</description>
      <category>일상/ETC</category>
      <author>BaaaaaaaaaaaaaaaaaaaaaaarkingDog</author>
      <guid isPermaLink="true">https://baaaaaaaaaaaaaaaaaaaaaaarkingdog.tistory.com/1091</guid>
      <comments>https://baaaaaaaaaaaaaaaaaaaaaaarkingdog.tistory.com/1091#entry1091comment</comments>
      <pubDate>Wed, 31 Jan 2024 17:40:03 +0900</pubDate>
    </item>
    <item>
      <title>[실전 알고리즘] 부록 B - 동적 배열</title>
      <link>https://baaaaaaaaaaaaaaaaaaaaaaarkingdog.tistory.com/1090</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;figure data-ke-type=&quot;video&quot; data-ke-style=&quot;alignCenter&quot; data-video-host=&quot;youtube&quot; data-video-url=&quot;https://www.youtube.com/watch?v=SOs_VoefLq8&quot; data-video-thumbnail=&quot;https://scrap.kakaocdn.net/dn/xPEP4/hyU85sjXMy/DxvLKpKkyBayWk4NwHIXHk/img.jpg?width=1280&amp;amp;height=720&amp;amp;face=0_0_1280_720&quot; data-video-width=&quot;860&quot; data-video-height=&quot;484&quot; data-video-origin-width=&quot;860&quot; data-video-origin-height=&quot;484&quot; data-ke-mobilestyle=&quot;widthContent&quot; data-video-title=&quot;[바킹독의 실전 알고리즘] 부록 B - 동적 배열&quot; data-original-url=&quot;&quot;&gt;&lt;iframe src=&quot;https://www.youtube.com/embed/SOs_VoefLq8&quot; width=&quot;860&quot; height=&quot;484&quot; frameborder=&quot;&quot; allowfullscreen=&quot;true&quot;&gt;&lt;/iframe&gt;
&lt;figcaption style=&quot;display: none;&quot;&gt;&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/boTj8n/btsD6vzGMO3/RMfohr8YkffkO20hikKtn0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/boTj8n/btsD6vzGMO3/RMfohr8YkffkO20hikKtn0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/boTj8n/btsD6vzGMO3/RMfohr8YkffkO20hikKtn0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FboTj8n%2FbtsD6vzGMO3%2FRMfohr8YkffkO20hikKtn0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1920&quot; height=&quot;1080&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;네 반갑습니다. 부록 B를 바로 시작하겠습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/u2QDc/btsD2HuOYB0/k2WcQF09s8k7JpSTkgvKW0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/u2QDc/btsD2HuOYB0/k2WcQF09s8k7JpSTkgvKW0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/u2QDc/btsD2HuOYB0/k2WcQF09s8k7JpSTkgvKW0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fu2QDc%2FbtsD2HuOYB0%2Fk2WcQF09s8k7JpSTkgvKW0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1920&quot; height=&quot;1080&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;부록답게 내용이 진짜 되게 짧습니다. 연습 문제도 따로 없습니다. 구현을 같이 해볼게 하나 있긴 하지만 그렇게 어렵지는 않을 것입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bvqIJP/btsD3MvnYqR/9vhnhRMknmaGirOobfY7O1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bvqIJP/btsD3MvnYqR/9vhnhRMknmaGirOobfY7O1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bvqIJP/btsD3MvnYqR/9vhnhRMknmaGirOobfY7O1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbvqIJP%2FbtsD3MvnYqR%2F9vhnhRMknmaGirOobfY7O1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1920&quot; height=&quot;1080&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;초심으로 돌아가서 0x03강 &amp;ndash; 배열에서 같이 짰던 코드를 잠깐 가져왔습니다. 당시에 이렇게 템플릿을 두고 insert 함수랑 erase 함수를 채워보라고 했는데, 그런데 insert를 여러번 해서 길이가 10 이상이 되면 어떻게 할까요? 그렇다고 하면 arr를 선언할 때 크기를 10 말고 100으로 둔다던가 하는 식으로 더 크게 둘 수 있긴한데, 좀 더 키워서 100으로 뒀다고 하면 insert가 100번 일어났을 때 또 문제가 됩니다. 사실 배열 단원에서는 이런 상황을 아예 언급을 안했습니다. 너무 초반 단원이라 이런 것까지 다루기는 조금 어려웠습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;그런데 그럼에도 불구하고 댓글로 혹시 insert가 계속 발생해서 배열 크기를 넘어서면 어떻게 해야하냐 이런 질문을 많이 받았습니다. 만약 본인이 이런 질문을 했거나, 혹은 질문을 댓글로 남가지는 않았더라도 배열 단원을 공부할 당시에 혼자서 이런 의문을 고민해보셨다면 진짜 완전 칭찬드립니다. 정말 좋은, 뭐랄까 프로그래머의 자질이 충분히 있다고 할까요. 이런걸 꼼꼼하게 따지고 뭔가 버그가 터질 것 같은 곳을 잘 잡아내는건 정말 중요한 역량입니다..&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/b9xDYj/btsD4kZQI3H/lkSjHffrUGY4yLpyTAxyp1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/b9xDYj/btsD4kZQI3H/lkSjHffrUGY4yLpyTAxyp1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/b9xDYj/btsD4kZQI3H/lkSjHffrUGY4yLpyTAxyp1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fb9xDYj%2FbtsD4kZQI3H%2FlkSjHffrUGY4yLpyTAxyp1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1920&quot; height=&quot;1080&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;배열 단원에서 같이 구현한 것 처럼 단순히 최대 크기를 정해두는 방식 말고 배열의 크기를 필요에 따라 늘렸다 줄였다 하려면 동적 배열이라는 개념이 필요합니다. C에서는 malloc이 쓰입니다. 학부때 이걸 말록이라고 하니까 교수님이 기겁을 했던 그런 기억이 있네요. 아무튼 C에는 malloc과 free를 쓰는데 C++에서는 new와 delete를 씁니다. 저희가 여기서 쓸 상황에서는 둘 다 큰 차이가 없어서 malloc이랑 free만 이전에 알고 있었다라고 해도 코드를 이해하는데에는 큰 문제는 없습니다. 그런데 malloc, new 이런걸 아예 처음 보고 동적할당이라는 개념이 안 익숙하시면 지금 한 번 관련 내용을 찾아보시는걸 추천드립니다. 엄청 깊게 알 필요는 없고 그냥 구글에 C++ 배열 동적 할당 이렇게 검색해서 대충만 파악하면 괜찮습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;설명을 다시 이어가면 insert 횟수에 제한을 따로 두고 싶지 않다고 하면 원소들을 담을 배열을 정적 배열에서 동적 배열로 바꾸고 insert를 많이 해서 배열이 꽉 찼을 때 그 크기를 늘려주는 방식으로 해결이 쉽게 될 것 같다는 생각을 할 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/d31ZPw/btsD286WRVc/aU4SZoCUIh2DVQyxujsKI1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/d31ZPw/btsD286WRVc/aU4SZoCUIh2DVQyxujsKI1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/d31ZPw/btsD286WRVc/aU4SZoCUIh2DVQyxujsKI1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fd31ZPw%2FbtsD286WRVc%2FaU4SZoCUIh2DVQyxujsKI1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1920&quot; height=&quot;1080&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;기본적으로는 앞에서 말한게 맞습니다. 앞에서 말한대로 구현을 하면 되는데 사실은 시간복잡도와 관련해서 조금 더 같이 확인해봐야 할게 있습니다. 일단 처음에는 insert를 하다가 공간이 꽉 차면 1칸을 늘릴 계획입니다. 그러니까 1칸을 더 키운 크기만큼의 공간을 할당받으면 됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/btF4Sg/btsDZ4j3ttu/wzyE4SHcuRJ8W44mgDy1I1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/btF4Sg/btsDZ4j3ttu/wzyE4SHcuRJ8W44mgDy1I1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/btF4Sg/btsDZ4j3ttu/wzyE4SHcuRJ8W44mgDy1I1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbtF4Sg%2FbtsDZ4j3ttu%2FwzyE4SHcuRJ8W44mgDy1I1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1920&quot; height=&quot;1080&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이렇게 메모리가 있다고 할 때 처음에는 3칸짜리로 잡아뒀다고 하겠습니다. new로 3칸을 요청하면 알아서 메모리의 어딘가를 받게 됩니다. 그리고 거기에 이렇게 insert가 다 됐다고 하면 4칸을 새로 받아야 하는데 언뜻 생각하기에는 그냥 저 3칸짜리 뒤에다가 받으면 안되나 싶을 수 있습니다. 그런데 아쉽게도 그럴 수는 없습니다. 이런 동적 할당이 실제 내부에서 어떻게 동작하는지는 컴퓨터 구조 같은 더 심화된 교과목을 배우면 알 수 있지만 당장 지금 그런 내용을 다룰건 아니고 어떤 느낌으로 이해를 하실 수 있냐면 메모리는&amp;nbsp;이곳&amp;nbsp;저곳에서&amp;nbsp;다&amp;nbsp;쓰고&amp;nbsp;있으니 저 뒤의 칸이 비어있다는 보장이 없습니다. 그래서 4칸을 새로 받게 되면 아예 새로운 곳에서 4칸을 잡게 됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/MNboq/btsDZ27Ak6K/FkjWNNQKDLsALTSa4EkriK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/MNboq/btsDZ27Ak6K/FkjWNNQKDLsALTSa4EkriK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/MNboq/btsDZ27Ak6K/FkjWNNQKDLsALTSa4EkriK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FMNboq%2FbtsDZ27Ak6K%2FFkjWNNQKDLsALTSa4EkriK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1920&quot; height=&quot;1080&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그래서 분홍색 4칸을 새로 할당을 받았으면 일단 바로 해줘야하는 조치가 있는데 당연히&amp;nbsp;새롭게&amp;nbsp;할당을&amp;nbsp;받으면&amp;nbsp;저기에&amp;nbsp;값이&amp;nbsp;제대로&amp;nbsp;써있지가&amp;nbsp;않습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bzCtW6/btsD2vg3gmQ/m9Ky40YPAfFEynaEe3NX0k/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bzCtW6/btsD2vg3gmQ/m9Ky40YPAfFEynaEe3NX0k/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bzCtW6/btsD2vg3gmQ/m9Ky40YPAfFEynaEe3NX0k/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbzCtW6%2FbtsD2vg3gmQ%2Fm9Ky40YPAfFEynaEe3NX0k%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1920&quot; height=&quot;1080&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그러면 저 4, 6, 3이라는 값을 옮겨써야 합니다. 그리고 원래 배열의 길이가 N이었다고 하면 이거 자체가 이미 O(N)입니다. 그러면 예를 들어서 마치 vector의 push_back 마냥 insert를 맨 뒤에 한다고 하면 이건 O(1)이기를 기대하는데 배열이 꽉 찼을 경우에는 당장 새 배열을 잡고 데이터를 옮기는 것 만으로 O(N)이 필요합니다. 이건 전혀 원치 않는 상황입니다. 그러면 지금 상황에서는 크기를 1씩 늘리다보니 매번 insert를 할 때 마다 확장이 발생해서 이런거니까 1씩 말고 한 3씩 늘린다고 하면 해결이 가능할까요? 아쉽게도 그렇지 않습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/nbWGh/btsD4ITHXCT/2GWlQJX36IEIzfVCX4FHEk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/nbWGh/btsD4ITHXCT/2GWlQJX36IEIzfVCX4FHEk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/nbWGh/btsD4ITHXCT/2GWlQJX36IEIzfVCX4FHEk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FnbWGh%2FbtsD4ITHXCT%2F2GWlQJX36IEIzfVCX4FHEk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1920&quot; height=&quot;1080&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;길이를 3씩 늘린다고 하면 insert를 3번 할 때 마다 전체 배열을 복사해야 하니 3번에 한 번씩 O(N)입니다. 그리고 이건 여전히 평균적으로 O(N)입니다. 3이&amp;nbsp;아니라&amp;nbsp;100,&amp;nbsp;1000&amp;nbsp;이렇게&amp;nbsp;하더라도&amp;nbsp;O(N)인건&amp;nbsp;달라지지가&amp;nbsp;않습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;늘리는 크기를 1000과 같이 엄청 크게 잡으면 이론적으로는 삽입이 O(N)일지언정 사실 1000번에 한 번만 O(N)이고 나머지는 다 O(1)이어서 실제 사용을 하는데에는 크게 문제가 없습니다. 하지만 이 경우에는 길이가 짧은 배열에도 너무 많은 공간을 할당하고 있어야 하는 문제가 있을 수 있습니다. 예를 들어서 길이 50 정도의 배열만 필요한데 확장이 한번 일어나면 바로 내부적으로는 크기가 1000을 넘어버리니 메모리의 관점에서 비효율적입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;현재 상황을 다시 정리해보면 배열이 꽉 찼을 때 배열을 1이나 1000 같은 상수 크기만큼 늘리는 방법을 쓰면 삽입의 시간복잡도가 배열의 복사 때문에 평균적으로 O(N)입니다. 늘리는 상수를 엄청 크게 두면 사실 이론적으로는 O(N)이라도 현실적으로 쓸 때에는 실행 시간이 크게 문제가 되지 않을 수 있지만 그렇게&amp;nbsp;되면&amp;nbsp;낭비하는&amp;nbsp;공간이&amp;nbsp;너무&amp;nbsp;많아질&amp;nbsp;수&amp;nbsp;있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bbFtJ5/btsD3LXzt1N/3IRkNQcYNOFvzLvVvb9vjk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bbFtJ5/btsD3LXzt1N/3IRkNQcYNOFvzLvVvb9vjk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bbFtJ5/btsD3LXzt1N/3IRkNQcYNOFvzLvVvb9vjk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbbFtJ5%2FbtsD3LXzt1N%2F3IRkNQcYNOFvzLvVvb9vjk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1920&quot; height=&quot;1080&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;여기서 놀랍게도 시간복잡도도 평균적으로 O(1)이고 공간도 낭비하지 않는 방법이 있습니다. 방법 자체는 되게 간단한데, 배열 크기를 상수 크기만큼 늘리는게 아니라 2배씩 늘리면 됩니다. 예를 들어서 원래 크기가 3이었다면 꽉 찼을 때 6으로 늘리고 그 다음으로 다시 꽉 차면 12로 늘립니다. 이렇게 하면 평균적으로 O(1)이 됩니다. 엄밀하게 말하면 amortized O(1)이라고 하는데 좀 낯선 단어일 것 같습니다. 일단 저게 왜 O(1)인건지 좀 감이 안올거라 설명을 더 드리겠습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/DBVT2/btsD262om2f/Q8gubBSfSHiLjCTsegRyB0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/DBVT2/btsD262om2f/Q8gubBSfSHiLjCTsegRyB0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/DBVT2/btsD262om2f/Q8gubBSfSHiLjCTsegRyB0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FDBVT2%2FbtsD262om2f%2FQ8gubBSfSHiLjCTsegRyB0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1920&quot; height=&quot;1080&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;바로 그냥 수식을 놓고 따져볼건데 편의상 시작 길이는 1이고 크기가 2배씩 커진다고 하겠습니다. 그러면 배열의 크기는 1, 2, 4, 8, ... 이렇게 2의 거듭제곱이 되고 또 다르게 표현하면 배열의 크기가 1, 2, 4, 8, ... 일 때 확장이 이루어집니다. 그리고 insert를 총 N = 2^k번 한다고 할 때의 전체 시간복잡도를 생각해보겠습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bgPgNL/btsD5weqxK0/5hDinDJ3blxDmxJwBK7qxK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bgPgNL/btsD5weqxK0/5hDinDJ3blxDmxJwBK7qxK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bgPgNL/btsD5weqxK0/5hDinDJ3blxDmxJwBK7qxK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbgPgNL%2FbtsD5weqxK0%2F5hDinDJ3blxDmxJwBK7qxK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1920&quot; height=&quot;1080&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;일단 N번, 즉 2^k번 insert를 할 때 마다 뒤에 대입을 하는 1번의 연산은 필요하고, 그리고 크기가 1, 2, 4, ..., 2^k일 때 확장이 발생하는데 확장이 이루어질 때 마다 현재 크기만큼의 데이터를 옮겨야 하니 시간복잡도에 1 + 2 + 4 + ... + 2^k가 추가됩니다. 다 합하면 대략 3N정도 나오고 이건 O(N)이라고 볼 수 있습니다. 즉 N번 insert를 할 때 O(N)이 들기 때문에 1번의 insert는 O(N)을 N으로 나눠서 O(1)이다, 정확히는 Amortized O(1)이다라고 표현을 합니다.&amp;nbsp; 엄밀히 따졌을 때 Amortized는 평균, 즉 Average와 약간의 뉘앙스 차이가 있지만 그 디테일은 그냥 넘어가고 결론적으로 2배 확장을 하는 기법을 사용하면 삽입이 O(1)이 된다고 이해를 하겠습니다. Amortized의 정확한 정의를 여기서 다루지는 않을거지만 어떤 느낌만 가져가시면 되냐면, 딱 한번 insert를 하면 운이 나쁠 경우엔 하필 그 때 확장하는 타이밍에 딱 걸려서 O(N)이 될 수 있습니다. 하지만 insert를 여러번 하면 반드시 평균적으로 O(1)이 된다는걸 알면 됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 동적배열을 같이 구현을 해보겠습니다. 그런데 일단 기본적으로 동적 배열이 필요하면 vector를 쓰면 됩니다. vector를 안쓰고 굳이 이걸 직접 구현을 할 일은 없습니다. 그전에는 그나마 삼성 B형 때문에 이런걸 습득하기도 했는데 2024년 1월 기준으로 이제 삼성 B형도 STL을 쓸 수 있게 해주기도 해서 더 필요가 없습니다. 그래서 그냥 vector의 동작 원리를 이해한다는 차원에서, 또 거기에 더해 구현 연습을 한다는 차원에서 같이 구현을 해보겠습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/b7FWjL/btsD0FEtEEz/Ut6TZqffTxQihdRS4afuOK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/b7FWjL/btsD0FEtEEz/Ut6TZqffTxQihdRS4afuOK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/b7FWjL/btsD0FEtEEz/Ut6TZqffTxQihdRS4afuOK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fb7FWjL%2FbtsD0FEtEEz%2FUt6TZqffTxQihdRS4afuOK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1920&quot; height=&quot;1080&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;배열 단원에서 했던 것과 약간은 비슷한데, 큰 차이는 배열이 동적 배열이 됐고 그리고 capacity라는 새 변수가 생겼습니다. capacity는 arr 배열이 점유하고 있는 크기를 의미합니다. 다르게 표현하면 삽입이 가능한 최대 크기입니다. 그리고 이전에는 길이를 신경쓰지 않고 그냥 막 insert 함수에서 삽입을 처리하는 12번째 줄에서 15번째 줄의 코드를 실행시키면 됐는데 이번에는 그렇지가 않고 어떤 조건이 만족되면 배열을 확장해줘야 합니다. 그 조건은 08번째 줄에 잘 채워넣으면 되고, 또 확장을 어떤 식으로 해야할지는 expand 함수에 구현을 해보면 됩니다. 실제 깃헙 &lt;a href=&quot;https://github.com/encrypted-def/basic-algo-lecture/blob/master/Appendix%20B/dynamic_array_test.cpp&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;링크&lt;/a&gt;에 들어가서 insert_test 함수를 보면 거기에 삽입이 발생할 때 마다 len, capacity 값이 어떻게 되는지를 적어놔서 상황을 이해하는데에 도움이 될 수도 있습니다. 다음 슬라이드에 바로 답이 나옵니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cUrnFc/btsD09ZAx89/BgXeQWQkM7C3dy6NRzVJOK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cUrnFc/btsD09ZAx89/BgXeQWQkM7C3dy6NRzVJOK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cUrnFc/btsD09ZAx89/BgXeQWQkM7C3dy6NRzVJOK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcUrnFc%2FbtsD09ZAx89%2FBgXeQWQkM7C3dy6NRzVJOK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1920&quot; height=&quot;1080&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;우선 22번째 줄의 조건을 보면, 확장은 len과 capacity가 같을 때 이루어져야 합니다. len과 capacity가 같다는건 더 이상 삽입이 불가능하다는 뜻이기 때문입니다. 그리고 expand를 보면 그냥 2 * capacity 크기의 새 배열 tmp를 잡고, arr에 있던 데이터를 tmp로 옮겨준 다음에 arr를 tmp로 바꾸면 됩니다. 포인터에 익숙하지 않으면 약간 헤멜 수는 있지만 제 생각에 이정도는 당장은 헷갈리더라도 약간만 시간을 들여서 보면 충분히 이해할 수 있을 것 같아서 더 설명은 하지 않겠습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그런데 하나 생각해볼 점은, 문제 풀이를 할 때 사실 동적 배열을 1개 쓸거면 동적 배열을 굳이 써야 할 필요가 없습니다. 1개밖에 없으면 애초에 메모리 제한을 전혀 걱정할 필요가 없는 상황입니다. 그러면 그냥 스택/큐/덱 단원에서 하던 것 처럼 배열을 처음에 엄청 크게 잡아버리면 됩니다. 그래서 동적 배열이 여러개 필요해야 이걸 직접 구현해서 정말 쓰임새 있게 쓸 수 있는거고 그렇게 여러개를 쓰려면 이거를 클래스로 만들어놓는게 좋습니다. 새 문법을 안건드리고 싶어서 여기 구현체에서는 클래스를 안쓰고 죄다 전역 변수로 뒀지만, 진짜 동적 배열을 제대로 써먹고 싶다 하면 클래스로 만들어보는걸 추천드립니다. 그런데 사실 앞에서도 말했지만 그냥 vector를 쓰면 되고 굳이 내가 직접 동적 배열을 짤 일은 없긴 합니다. &lt;a href=&quot;https://github.com/encrypted-def/basic-algo-lecture/blob/master/Appendix%20B/dynamic_array_test_ans.cpp&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;(링크)&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/N0hS9/btsD0Gi2r8S/VdYxKFiwRDtiPBJgbqnUwk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/N0hS9/btsD0Gi2r8S/VdYxKFiwRDtiPBJgbqnUwk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/N0hS9/btsD0Gi2r8S/VdYxKFiwRDtiPBJgbqnUwk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FN0hS9%2FbtsD0Gi2r8S%2FVdYxKFiwRDtiPBJgbqnUwk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1920&quot; height=&quot;1080&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이렇게 동적 배열 단원이 스무스하게 끝났습니다. 뭐 엄청 특별한건 없고 vector의 내부 동작 원리를 이해하는 차원에서 설명을 드렸으니 혹시&amp;nbsp;vector가 실제로는 어떻게 구현이 되어있나 궁금하셨다면 이 강의를 통해서 의문을 해결하실 수 있었을 것입니다. 연습 문제도 따로 없으니 가볍게 본걸로 만족하고 강의를 마치도록 하겠습니다..&lt;/p&gt;</description>
      <category>강좌/실전 알고리즘</category>
      <author>BaaaaaaaaaaaaaaaaaaaaaaarkingDog</author>
      <guid isPermaLink="true">https://baaaaaaaaaaaaaaaaaaaaaaarkingdog.tistory.com/1090</guid>
      <comments>https://baaaaaaaaaaaaaaaaaaaaaaarkingdog.tistory.com/1090#entry1090comment</comments>
      <pubDate>Sat, 27 Jan 2024 19:00:20 +0900</pubDate>
    </item>
    <item>
      <title>최근에 삼성전자 B형 / PRO 치신분께 질문</title>
      <link>https://baaaaaaaaaaaaaaaaaaaaaaarkingdog.tistory.com/1089</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;미루고 미루다가 큰 맘 먹고 강의를 다시 만들고있는데, 궁금한게 있어서 최근에 삼성전자 B형 / PRO 치신분께 질문을 드립니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;혹시 삼성전자 B형 / PRO에서 STL을 허용하나요? 옛날엔 안됐는데 최근에는 허용한다는 얘기를 들은 것 같은데 물어볼 곳이 없네요,, 댓글 남겨주시면 감사링&lt;/p&gt;</description>
      <category>일상/ETC</category>
      <author>BaaaaaaaaaaaaaaaaaaaaaaarkingDog</author>
      <guid isPermaLink="true">https://baaaaaaaaaaaaaaaaaaaaaaarkingdog.tistory.com/1089</guid>
      <comments>https://baaaaaaaaaaaaaaaaaaaaaaarkingdog.tistory.com/1089#entry1089comment</comments>
      <pubDate>Fri, 26 Jan 2024 22:19:19 +0900</pubDate>
    </item>
    <item>
      <title>내가 누구? &amp;quot;요아소비 내한 티켓 owner&amp;quot;</title>
      <link>https://baaaaaaaaaaaaaaaaaaaaaaarkingdog.tistory.com/1088</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;598&quot; data-origin-height=&quot;414&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/phawi/btsBQSlphBw/V9ix9JOsGl0axrl7J45v3K/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/phawi/btsBQSlphBw/V9ix9JOsGl0axrl7J45v3K/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/phawi/btsBQSlphBw/V9ix9JOsGl0axrl7J45v3K/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fphawi%2FbtsBQSlphBw%2FV9ix9JOsGl0axrl7J45v3K%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;598&quot; height=&quot;414&quot; data-origin-width=&quot;598&quot; data-origin-height=&quot;414&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;야미~&lt;/p&gt;</description>
      <category>일상/의식의 흐름</category>
      <author>BaaaaaaaaaaaaaaaaaaaaaaarkingDog</author>
      <guid isPermaLink="true">https://baaaaaaaaaaaaaaaaaaaaaaarkingdog.tistory.com/1088</guid>
      <comments>https://baaaaaaaaaaaaaaaaaaaaaaarkingdog.tistory.com/1088#entry1088comment</comments>
      <pubDate>Thu, 14 Dec 2023 01:03:42 +0900</pubDate>
    </item>
    <item>
      <title>숙원 사업 해결</title>
      <link>https://baaaaaaaaaaaaaaaaaaaaaaarkingdog.tistory.com/1087</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://github.com/encrypted-def/my-ctf-challenges/tree/main&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://github.com/encrypted-def/my-ctf-challenges/tree/main&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1698600175491&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;object&quot; data-og-title=&quot;GitHub - encrypted-def/my-ctf-challenges: My ctf challenges, mostly cryptography&quot; data-og-description=&quot;My ctf challenges, mostly cryptography. Contribute to encrypted-def/my-ctf-challenges development by creating an account on GitHub.&quot; data-og-host=&quot;github.com&quot; data-og-source-url=&quot;https://github.com/encrypted-def/my-ctf-challenges/tree/main&quot; data-og-url=&quot;https://github.com/encrypted-def/my-ctf-challenges&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/u9RUT/hyUnRsU3Ck/qOsGrIP3zcuvT0TKyrqrq1/img.png?width=1200&amp;amp;height=600&amp;amp;face=0_0_1200_600&quot;&gt;&lt;a href=&quot;https://github.com/encrypted-def/my-ctf-challenges/tree/main&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://github.com/encrypted-def/my-ctf-challenges/tree/main&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/u9RUT/hyUnRsU3Ck/qOsGrIP3zcuvT0TKyrqrq1/img.png?width=1200&amp;amp;height=600&amp;amp;face=0_0_1200_600');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;GitHub - encrypted-def/my-ctf-challenges: My ctf challenges, mostly cryptography&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;My ctf challenges, mostly cryptography. Contribute to encrypted-def/my-ctf-challenges development by creating an account on GitHub.&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;github.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;4시간을 바쳐 이때까지 냈던 CTF 문제들을 전부 모았습니다!&lt;/p&gt;</description>
      <category>일상/ETC</category>
      <author>BaaaaaaaaaaaaaaaaaaaaaaarkingDog</author>
      <guid isPermaLink="true">https://baaaaaaaaaaaaaaaaaaaaaaarkingdog.tistory.com/1087</guid>
      <comments>https://baaaaaaaaaaaaaaaaaaaaaaarkingdog.tistory.com/1087#entry1087comment</comments>
      <pubDate>Mon, 30 Oct 2023 02:23:15 +0900</pubDate>
    </item>
    <item>
      <title>ㅇㄹㅂㄷ</title>
      <link>https://baaaaaaaaaaaaaaaaaaaaaaarkingdog.tistory.com/1086</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;평화로운 월요일 아침입니다. 어제 11시 조금 넘어서 잤는데도 주말에 잠을 엄청 자서 그런가 6시에 눈이 떠졌네요. 꿈에서 뜬금없이 중학교로 돌아갔는데, 마땅히 한건 없지만 그래도 즐거웠습니다,,&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;왜 벌써 2023년은 세 달밖에 남지 않은 것인가 상당히 마음이 아픈 부분입니다. 뭔가 바쁜듯 안바쁜듯 시간이 훅 갔네요. 사실 좀 바빴음..&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;아마 10월 중순까지는 논문 작업하느라 계속 바쁠 것 같고 그 이후는 연말까지 좀 여유롭게 있을 수 있지 않을까 싶습니다. 이젠 ㄹㅇ 제 연구를 해야하는 느낌이라고 할까요. 논문 실적 빠방하게 들고 남은 대학원 생활 룰ㄹ루랄라 즐겁게 보내고 싶습니다 껄껄&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;작년에 스노보드를 2번 가서 찍먹해봤는데 너무 재밌었습니다. 그래서 올해는 제대로 타보고 싶어서 초보자 스타터팩 느낌으로 일단 장비는 당근마켓으로 샀고, 무주 스키장 시즌권도 기다리고 있습니다. 이런 점에서는 스스로 돈을 버는 으른이 좋네요. 마침 오늘이 대학원 월급날입니다. 77ㅓ억~&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;친구의 꼬드김으로 말해보카라는 앱으로 영어 공부를 계속 하고 있는데 앱이 정말 좋습니다. 사실 이런거에 돈 쓰는걸 굉장히 싫어해서 처음에 좀 써보다가 더 쓰려면 결제가 필요하길래 구글에 &quot;말해보카 비슷한 무료앱&quot; 이런식으로 검색했는데 마땅한 대체제가 없길래 그냥 결제했습니다. 하루에 단어 30개씩 익히려고 하는데, just as나 as to 같이 단어 자체가 엄청 어려운게 아닌데 막상 뜻은 잘 모르겠는 그런 것들을 잘 알게 되어서 굉장히 만족하고 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;8월에 데프콘 갔다온걸 브이로그로 올리고 싶은데 계속 미루고 있습니다. 챗gpt가 이런건 안해주나..&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그럼 이번 주 한주도 화이팅~~&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>일상/의식의 흐름</category>
      <author>BaaaaaaaaaaaaaaaaaaaaaaarkingDog</author>
      <guid isPermaLink="true">https://baaaaaaaaaaaaaaaaaaaaaaarkingdog.tistory.com/1086</guid>
      <comments>https://baaaaaaaaaaaaaaaaaaaaaaarkingdog.tistory.com/1086#entry1086comment</comments>
      <pubDate>Mon, 25 Sep 2023 07:59:13 +0900</pubDate>
    </item>
    <item>
      <title>사는 얘기</title>
      <link>https://baaaaaaaaaaaaaaaaaaaaaaarkingdog.tistory.com/1085</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;요즘 별 일 없이 잘 지내고 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이번주가 시험기간이긴 한데 듣는 과목도 시험이 없고 TA하는 과목도 시험이 없어서 학기는 저번주에 끝난 느낌입니다. 수업이랑 TA가 엄청 시간을 뺏기는건 아닌데 그래도 어쨌거나 계속 수업을 가야하니 흐름이 계속 끊겼는데 이제 좀 더 연구에 집중을 할 수 있을 것만 같은 느낌....? 그리고 학식 줄도 더 짧아지겠죠 매우 개꿀입니다&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;대학원 전체 과정중에 벌써 절반이 지났다는걸 깨닫고 충격-경악이었습니다. 시간이 넘나 빠릅니다. 다행히 저는 크게 힘든 것 없이 현재의 삶에 굉장히 만족하면서 지내고 있고 논문만 잘 나온다면 정말 즐겁게 대학원생활 끝까지 잘 마무리할 것 같습니다. 논문만 잘 나온다면,,,, 그래도 저번 주말에 작고 미약하지만 (제 생각에 처음으로 그럴듯한) 아이디어 하나가 생겨서 논의를 해보고 있고 선배 아이디어로 진행중인 논문에 들어가있는 것도 있고 뭐 그러고 있습니다. 개인적으로는 대학원 다니는 동안에 제가 주도적으로 프리미티브 제안하는 논문도 하나 써보고 싶고, 공격 논문도 하나 써볼 수 있다면 상당히 기쁠 것 같습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;봄쯤이었나에 여름에는 락페스티벌 다니고 겨울에는 스키장 다녀야지하고 생각은 했는데 막상 여름이 되니 귀찮네요,, 펜타포트 라인업을 봤는데 검정치마를 한 번 보고 싶긴 하지만 그렇다고 1일권 끊는다고 쳐도 12만원은 좀 너무 비쌉니다..ㅠ 2일차 라인업에서 검정치마 말고는 크게 관심있는 밴드가 없어서,, 눈물의 땡처리 티켓이 어케저케 나오면 갈 것 같은데 아니면 검정치마는 다음 기회에,,,&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이번주 코드게이트 예선에 문제 출제했습니다. 개인적으로 상당히 잘 낸 것 같아 만족스러운데 많은 참여 부탁,,!!&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;요새 j pop 많이 듣고 유다빈밴드 노래도 많이 듣습니다. 기타로 커버해보고 싶은 노래도 많이 생겼네여&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>일상/의식의 흐름</category>
      <author>BaaaaaaaaaaaaaaaaaaaaaaarkingDog</author>
      <guid isPermaLink="true">https://baaaaaaaaaaaaaaaaaaaaaaarkingdog.tistory.com/1085</guid>
      <comments>https://baaaaaaaaaaaaaaaaaaaaaaarkingdog.tistory.com/1085#entry1085comment</comments>
      <pubDate>Tue, 13 Jun 2023 09:36:54 +0900</pubDate>
    </item>
    <item>
      <title>[실전 알고리즘] 부록 A - 문자열 기초</title>
      <link>https://baaaaaaaaaaaaaaaaaaaaaaarkingdog.tistory.com/1081</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;figure data-ke-type=&quot;video&quot; data-ke-style=&quot;alignCenter&quot; data-video-host=&quot;youtube&quot; data-video-url=&quot;https://www.youtube.com/watch?v=Mj6D3HW_rCw&quot; data-video-thumbnail=&quot;https://scrap.kakaocdn.net/dn/P19ne/hyStPFlPDM/bXozJBDuyOXWoSCJztnRH1/img.jpg?width=640&amp;amp;height=480&amp;amp;face=0_0_640_480&quot; data-video-width=&quot;640&quot; data-video-height=&quot;480&quot; data-video-origin-width=&quot;640&quot; data-video-origin-height=&quot;480&quot; data-ke-mobilestyle=&quot;widthContent&quot; data-video-title=&quot;[바킹독의 실전 알고리즘] 부록 A - 문자열 기초&quot; data-original-url=&quot;&quot;&gt;&lt;iframe src=&quot;https://www.youtube.com/embed/Mj6D3HW_rCw&quot; width=&quot;640&quot; height=&quot;480&quot; frameborder=&quot;&quot; allowfullscreen=&quot;true&quot;&gt;&lt;/iframe&gt;
&lt;figcaption style=&quot;display: none;&quot;&gt;&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cuuHoF/btr07A1qRHi/hTTpoSIcf4qbLvkREwMA81/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cuuHoF/btr07A1qRHi/hTTpoSIcf4qbLvkREwMA81/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cuuHoF/btr07A1qRHi/hTTpoSIcf4qbLvkREwMA81/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcuuHoF%2Fbtr07A1qRHi%2FhTTpoSIcf4qbLvkREwMA81%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1920&quot; height=&quot;1080&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;안녕하세요, 첫 번째 부록을 시작해봅시다. 부록도 0x01 0x02 0x03 이렇게 붙여야하나 고민을 좀 했는데 다른 책들을 보니 부록은 A, B, C로 붙이는게 국룰인 것 같아 부록 A로 이름 붙였습니다. 강의를 만들다보니 뭔가 추가적인 설명이 필요하겠다 하는 개념들이 있었는데 그렇다고 한 단원으로 만들기는 좀 애매한 내용들이 있어서 부록으로 소개해드리게 되었습니다. 예를 들어서 이번 부록에서 소개할 내용을 보면 제 강의 구성 상에서 KMP나 트라이와 같은 문자열 알고리즘이 제일 뒤에 나와서 문자열에 대한 기초적인 내용을 강의 극후반까지 소개를 못드렸고 이렇게 뒤늦게나마 메소드들을 소개하는 강의를 부록으로 만들게 되었습니다. 그래서 제 강의는 AS까지 확실히 해드린다는거 한 번 인지해주시고, 나중에 따로 어딘가에 적어두겠지만 부록 A, B, C는 0x11강 그리디까지 본 다음 익히고 부록 D, E는 0x1F강 트라이까지 본 후에 익히는 것을 의도하고 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/ySKwe/btr0VLbu3bU/POEJdNtsIPqkArpw2QRNt1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/ySKwe/btr0VLbu3bU/POEJdNtsIPqkArpw2QRNt1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/ySKwe/btr0VLbu3bU/POEJdNtsIPqkArpw2QRNt1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FySKwe%2Fbtr0VLbu3bU%2FPOEJdNtsIPqkArpw2QRNt1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1920&quot; height=&quot;1080&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이번 단원에서는 새로운 알고리즘이나 개념을 다루지는 않을거고 C++에서 문자열을 다루는 방법과 여러 메소드들을 알아보고자 합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/mEGmC/btr0VJrbyOk/YoDOwqxGPt4KnvEO0loTt0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/mEGmC/btr0VJrbyOk/YoDOwqxGPt4KnvEO0loTt0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/mEGmC/btr0VJrbyOk/YoDOwqxGPt4KnvEO0loTt0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FmEGmC%2Fbtr0VJrbyOk%2FYoDOwqxGPt4KnvEO0loTt0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1920&quot; height=&quot;1080&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;강의에 앞서 먼저 알려드리고 싶은게 있는데, 저는 알고리즘 문제를 풀 때 C++를 굉장히 선호하는 편임에도 불구하고 문자열 처리가 복잡할 때 만큼은 파이썬을 씁니다. 단순히 문자열을 이어붙이고, 단어를 찾는 정도야 C++로 못할건 없지만 그 정도가 아니라 예를 들어 HTML 파싱 처럼 일단 보면 딱 머리가 아픈 그런 문제를 보면 그냥 바로 파이썬을 꺼내듭니다. 그래서 인생은 짧기 때문에 파이썬이 필요하다는 교훈처럼 문자열 처리가 복잡하면 C++ 말고 파이썬을 쓰는걸 추천드립니다. 또 사실 명색이 개발자면 파이썬 정도는 익혀두면 두고두고 쓸 곳이 많기도 합니다. 하지만 현실적으로 파이썬으로 알고리즘 문제를 푼 경험이 많지 않으신 분이라면 문자열 처리 단 하나만 보고 파이썬을 새로 익히는건 다소 비효율적이긴 합니다. 그래서 파이썬도 보조 무기로 익혀둘지 그냥 C++로만 할지는 각자가 선택을 하면 되지만, 이런저런 이유로 꼭 C++로 문제를 풀어야만 하는 상황이라면 문자열을 char*으로 관리하는 대신 C++의 string을 사용하시는게 훨씬 낫습니다. char*는 지원하는 메소드도 불편하고 문자열 끝에 반드시 NULL이 있어야한다는 점 때문에 조금만 삐끗해도 버그를 발생시킬 수 있습니다. 혹시 학부때 프로그래밍 기초 강의에서 C언어로 과제를 해본적이 있다면 무슨 의미인지 쉽게 이해할 수 있을 것입니다. 비유를 해보자면 char*은 뗀석기, C++의 string은 간석기, 파이썬은 철기 이런 느낌이라 문자열 사용이 복잡할 경우에는 파이썬 사용을 추천하지만 꼭 C++로 구현을 하겠다면 char* 대신 string을 사용하는 것을 강력하게 추천합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/su6aP/btr1nEahj1x/yjC5iDxV5sd84y2JHqubm1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/su6aP/btr1nEahj1x/yjC5iDxV5sd84y2JHqubm1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/su6aP/btr1nEahj1x/yjC5iDxV5sd84y2JHqubm1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fsu6aP%2Fbtr1nEahj1x%2FyjC5iDxV5sd84y2JHqubm1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1920&quot; height=&quot;1080&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;사실 문제를 풀거나 개발을 하다보면 자연스럽게 문자열에 대한 처리가 필요한 일이 종종 있을 수 있어서 여기 나와있는 메소드 중에서 한 번쯤은 접해본게 있을 수도 있습니다. 각 메소드들을 보면 제가 여기 단순히 예시로 써놓은 방법 이외에도 인자를 추가로 넘겨서 유용하게 써먹을 수 있는 경우가 있긴 하지만 그런 것들을 하나하나 소개하기에는 너무 많아서 자세한건 문서를 참고해보시고 substr, replace, find, erase, insert 등이 있구나 하는 정도로만 이해하고 가겠습니다. 또한 find에서 존재하지 않을 경우에는 18번째 줄과 같이 string::npos를 반환하는데 string::npos는 사실 -1과 같기 때문에 find 결과가 없음을 확인하고 싶으면 -1과 비교를 해도 상관없습니다. &lt;a href=&quot;https://github.com/encrypted-def/basic-algo-lecture/blob/master/Appendix%20A/string_example.cpp&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;(코드)&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/rRErj/btr0WekrkNv/eNq4hfaOPKqGUTCvLM4cNK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/rRErj/btr0WekrkNv/eNq4hfaOPKqGUTCvLM4cNK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/rRErj/btr0WekrkNv/eNq4hfaOPKqGUTCvLM4cNK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FrRErj%2Fbtr0WekrkNv%2FeNq4hfaOPKqGUTCvLM4cNK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1920&quot; height=&quot;1080&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;C++ string에는 이렇게 메소드들이 적당히 있어서 적재적소에 써먹을 수 있지만 예를 들어 공백이나 콤마를 기준으로 단어를 나눌 때와 같이 구분자를 기준으로 문자열을 나눠주는 함수가 없습니다. 문자열 처리를 연습할겸 문자열 s를 받아 구분자 sep을 기준으로 문자열을 나눈 결과를 반환하는 split 함수를 작성해봅시다. sep은 꼭 1글자일 필요가 없다는 점에 유의하세요. 위의 string_example.cpp에서 제가 작성한 split 함수를 날리고 직접 만들어보세요.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bZOCZs/btr0RPrKmHv/6PjdH7VHdZKkM3tOoAhGk0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bZOCZs/btr0RPrKmHv/6PjdH7VHdZKkM3tOoAhGk0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bZOCZs/btr0RPrKmHv/6PjdH7VHdZKkM3tOoAhGk0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbZOCZs%2Fbtr0RPrKmHv%2F6PjdH7VHdZKkM3tOoAhGk0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1920&quot; height=&quot;1080&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;저는 find 함수의 2번째 인자로 처음 탐색을 시작할 위치를 보낼 수 있다는 사실을 이용해 s 안에 sep이 있는 위치들을 찾아 적절하게 단어를 잘라 vector ret에 저장했습니다. 여기서 구현의 편의를 위해 pos를 두는 대신 s라는 문자열 자체를 s = s.substr(nxt_pos + sep.size());와 같이 바꾸면서 처리를 할 수 있지만 이렇게 될 경우 본문에 써놓은 것과 같이 A A A ... A와 같은 문자열에서 공백을 기준으로 분리할 때 O(|S|)가 아니고 O(|S|&lt;sup&gt;2&lt;/sup&gt;)에 동작한다는 단점이 있습니다. 왜 O(|S|&lt;sup&gt;2&lt;/sup&gt;)이냐면 공백으로 저 문자열을 분리할 경우 단어가 대략 |S|/2개 생기기 때문에 s에 s.substr(nxt_pos + sep.size());를 대입하는 연산이 대략 |S|/2번 발생하고, 또 각 연산에 필요한 시간복잡도가 평균적으로 O(|S|)여서 그렇습니다. 그렇기 때문에 지금의 코드와 같이 pos라는 인덱스 정보만 별도로 가지고 다니면서 필요에 따라 substr로 문자열을 자르는 방식으로 구현하는걸 추천드립니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/5re1K/btr07ANZAOU/PFqPW0ft1pBT03PxcKa160/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/5re1K/btr07ANZAOU/PFqPW0ft1pBT03PxcKa160/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/5re1K/btr07ANZAOU/PFqPW0ft1pBT03PxcKa160/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F5re1K%2Fbtr07ANZAOU%2FPFqPW0ft1pBT03PxcKa160%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1920&quot; height=&quot;1080&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;비단 split 함수가 아니더라도 문자열에서 무언가 연산을 할 때 시간복잡도를 고려하지 않는 경우를 종종 볼 수 있는데, 문자열의 길이가 이를테면 1000 이하 정도로 작아서 크게 시간복잡도가 상관이 없는 상황이라면 큰 문제가 없습니다. 하지만 길이가 10만 이상으로 커서 시간복잡도가 길이에 대한 제곱 이상일 때 시간 초과가 나는 경우라면 반드시 시간복잡도를 꼼꼼하게 따질 필요가 있습니다. &lt;/span&gt;이 주의사항은 제가 이 부록을 통해 꼭 전달을 해드리고 싶었던 내용이고 또 문자열과 관련해 흔하게 볼 수 있는 실수 중 하나입니다. 지금 이 코드의 시간복잡도는 얼마일까요? N은 반복 횟수인 1000000이라고 생각해서 시간복잡도가 N에 대해 어떻게 될지를 생각해보면 되겠습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bX1Ybd/btr1nwwzlTl/hdlKKvuWUArxT51Urc4ke0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bX1Ybd/btr1nwwzlTl/hdlKKvuWUArxT51Urc4ke0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bX1Ybd/btr1nwwzlTl/hdlKKvuWUArxT51Urc4ke0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbX1Ybd%2Fbtr1nwwzlTl%2FhdlKKvuWUArxT51Urc4ke0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1920&quot; height=&quot;1080&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;얼핏 보기에는 O(N)일 것 같지만 이 코드는 O(N&lt;sup&gt;2&lt;/sup&gt;)에 동작합니다. 써놓은 것 처럼 매 덧셈마다 새 객체를 만들고 그걸 s에 대입하기 때문에 그렇습니다. 당연히 a로 이루어진 길이 N의 문자열을 O(N&lt;sup&gt;2&lt;/sup&gt;)에 만들고 싶은 사람은 없을 것이기에 이걸 O(N)에 수행하도록 변경한 코드는 아래에서 확인 가능합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bf5F1W/btr1dd5IIDG/uRBeLntoPKNSjnh4rUkaBk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bf5F1W/btr1dd5IIDG/uRBeLntoPKNSjnh4rUkaBk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bf5F1W/btr1dd5IIDG/uRBeLntoPKNSjnh4rUkaBk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fbf5F1W%2Fbtr1dd5IIDG%2FuRBeLntoPKNSjnh4rUkaBk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1920&quot; height=&quot;1080&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;+= 연산자를 이용하면 시간복잡도가 더해지는 길이에만 영향을 받아 총 O(N)에 수행 가능합니다. 이 차이로 인해 뜬금없는 시간 초과를 받지 않도록 주의합시다. 이외에도 시간복잡도를 줄여야 할경우 split 함수에서 본 것과 같이 문자열 자체에서 삭제나 추가 등을 하는 대신 인덱스 정보만을 가지고 영리하게 처리할 수 있는 방법은 없을지 고민해보도록 합시다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/lpT05/btsdQf4lMtA/7HTFZun8vGfBKUD9rXXw0k/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/lpT05/btsdQf4lMtA/7HTFZun8vGfBKUD9rXXw0k/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/lpT05/btsdQf4lMtA/7HTFZun8vGfBKUD9rXXw0k/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FlpT05%2FbtsdQf4lMtA%2F7HTFZun8vGfBKUD9rXXw0k%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1920&quot; height=&quot;1080&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이제 바로 문제를 풀어봅시다. &lt;a href=&quot;https://www.acmicpc.net/problem/1543&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;BOJ 1543번: 문서 검색&lt;/a&gt;을 보시면 find 함수를 쓰면 되겠다는 느낌이 오고 또 find 함수에서는 pos 인자를 넘겨서 내가 찾고 싶은 단어가 위치 pos 이후로 언제 등장하는지를 알 수 있습니다. 이 때 이후라고 함은 위치 pos를 포함합니다. 저기 써놓은 T.find(P, pos)의 설명을 읽어보세요. &quot;abcabc&quot;.find(&quot;abc&quot;, 1)로 예를 들면 &quot;abcabc&quot;에서 &quot;abc&quot;가 등장하는 위치를 찾는데, 인덱스 1 이후의 위치를 찾기 때문에 3을 반환합니다. 그 밑의 예시는 직접 생각해보면 어렵지 않게 이해할 수 있을 것이라고 생각합니다. 이 pos 인자를 적절하게 정해서 중복되어 세는 것은 빼야한다는 조건을 처리할 방법을 고민해봅시다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/benBmv/btsdQLaOTtF/klzdLnhBQPTknYtl39kVK0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/benBmv/btsdQLaOTtF/klzdLnhBQPTknYtl39kVK0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/benBmv/btsdQLaOTtF/klzdLnhBQPTknYtl39kVK0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbenBmv%2FbtsdQLaOTtF%2FklzdLnhBQPTknYtl39kVK0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1920&quot; height=&quot;1080&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;방법은 비교적 간단합니다. find를 통해 단어를 찾은 이후에는 그 위치에서 P.size()만큼 더한 값을 pos의 인자로 넘기는 작업을 반복하면 됩니다. 이렇게 하는 대신 단순히 1만 더할 경우에는 예제 입력 4와 같이 &quot;aaaaaaa&quot;에서 &quot;aa&quot;의 등장 횟수를 셀 때 중복되는 경우가 생길 수 있습니다. 적힌 내용이 조금 헷갈리면 바로 코드를 보면서 이해해보도록 합시다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/mdv2i/btsdOBHnTq7/WoKAXZ1cHpFM2oucdMw2G0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/mdv2i/btsdOBHnTq7/WoKAXZ1cHpFM2oucdMw2G0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/mdv2i/btsdOBHnTq7/WoKAXZ1cHpFM2oucdMw2G0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fmdv2i%2FbtsdOBHnTq7%2FWoKAXZ1cHpFM2oucdMw2G0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1920&quot; height=&quot;1080&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;문제의 조건에서 문서와 단어에 공백이 있을 수 있다고 했으니 getline으로 입력을 받고 11-15번째 줄과 같이 이전에 단어가 등장한 위치를 f에 저장했다가 다음 탐색을 할 때에는 find의 pos 인자로 f + p.size()를 넘겨 중복되어 세지 않도록 했습니다. 인자로 넘기는게 f + p.size()인지, 아니면 f + p.size() + 1이나 f + p.size() - 1인지 등이 은근 헷갈릴 수 있고 이렇게 인덱스에서 1 차이로 혼돈이 오는건 비단 이 문제 뿐만 아니라 다른 문자열 문제에서도 비일비재한 일입니다. 그럴땐 차분하게 손으로 직접 작은 예시를 써보며 인덱스를 정확하게 맞추면 됩니다. &lt;a href=&quot;https://github.com/encrypted-def/basic-algo-lecture/blob/master/Appendix%20A/1543.cpp&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;(코드)&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/r8kEW/btsdNu2Q7HA/tWGR71MZ1KHUmRkjGjjbj0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/r8kEW/btsdNu2Q7HA/tWGR71MZ1KHUmRkjGjjbj0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/r8kEW/btsdNu2Q7HA/tWGR71MZ1KHUmRkjGjjbj0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fr8kEW%2FbtsdNu2Q7HA%2FtWGR71MZ1KHUmRkjGjjbj0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1920&quot; height=&quot;1080&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다음 문제는 &lt;a href=&quot;https://www.acmicpc.net/problem/2941&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;BOJ 2941번: 크로아티아 알파벳&lt;/a&gt;입니다. C++ string의 어떤 메소드를 활용하면 좋을까요?&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/nR6Uv/btsdQfcdwhJ/Opr3ZUes9yxauHKyWZryFk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/nR6Uv/btsdQfcdwhJ/Opr3ZUes9yxauHKyWZryFk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/nR6Uv/btsdQfcdwhJ/Opr3ZUes9yxauHKyWZryFk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FnR6Uv%2FbtsdQfcdwhJ%2FOpr3ZUes9yxauHKyWZryFk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1920&quot; height=&quot;1080&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;저는 replace를 이용해 크로아티아 알파벳을 계속 다른 문자로 치환하는 방법을 사용했습니다. 만약 크로아티아 알파벳을 그냥 지워버리면 어떤 문제가 있을까요?&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cIh2Ej/btsdQdFqNsR/gqNvke5xsTDl6rEP1lVmL0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cIh2Ej/btsdQdFqNsR/gqNvke5xsTDl6rEP1lVmL0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cIh2Ej/btsdQdFqNsR/gqNvke5xsTDl6rEP1lVmL0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcIh2Ej%2FbtsdQdFqNsR%2FgqNvke5xsTDl6rEP1lVmL0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1920&quot; height=&quot;1080&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그렇게 하면 nnjj와 같은 예시에서 오답을 낼 수 있습니다. 구현을 직접 해봅시다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/x76IO/btsdPKXQ8oc/XAuNyzRcsIx0oV5RiKyDak/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/x76IO/btsdPKXQ8oc/XAuNyzRcsIx0oV5RiKyDak/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/x76IO/btsdPKXQ8oc/XAuNyzRcsIx0oV5RiKyDak/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fx76IO%2FbtsdPKXQ8oc%2FXAuNyzRcsIx0oV5RiKyDak%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1920&quot; height=&quot;1080&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;구현에서 크게 특이사항은 없습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bDElOR/btsdRfvVS87/jqyrtbDZR8hqDjBLQmKx51/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bDElOR/btsdRfvVS87/jqyrtbDZR8hqDjBLQmKx51/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bDElOR/btsdRfvVS87/jqyrtbDZR8hqDjBLQmKx51/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbDElOR%2FbtsdRfvVS87%2FjqyrtbDZR8hqDjBLQmKx51%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1920&quot; height=&quot;1080&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이번 단원에서는 주로 C++ string의 사용법에 대해 알아보았습니다. 문자열 처리가 복잡한 문제들은 구현이 약간 까다롭게 느껴질 수 있지만 대부분 특별한 알고리즘이 필요한 문제들은 아니기 때문에 메소드들을 잘 익히고 인덱스 실수가 발생하지 않도록 주의하면서 문자열 관련 구현을 많이 연습해보다보면 그렇게 어렵지 않게 잘 풀어낼 수 있습니다.&lt;/p&gt;</description>
      <category>강좌/실전 알고리즘</category>
      <author>BaaaaaaaaaaaaaaaaaaaaaaarkingDog</author>
      <guid isPermaLink="true">https://baaaaaaaaaaaaaaaaaaaaaaarkingdog.tistory.com/1081</guid>
      <comments>https://baaaaaaaaaaaaaaaaaaaaaaarkingdog.tistory.com/1081#entry1081comment</comments>
      <pubDate>Wed, 3 May 2023 22:22:40 +0900</pubDate>
    </item>
    <item>
      <title>!</title>
      <link>https://baaaaaaaaaaaaaaaaaaaaaaarkingdog.tistory.com/1083</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;요새 ZKP를 열심히 보고 있습니다. 처음 시작은 대체 SNARK와 STARK가 어떻게 돌아가는건지를 알고싶다는거였는데 논문은 수학 범벅이라 도저히 논문으로 바로 시작할 용기는 안나고 인터넷에 설명글이나 영상은 많지만 또 그런건 아무래도 일반인을 대상으로 한거다보니 뭔가 2% 부족해서 상당히 답답했는데 그래도 어째저째 맨땅에 헤딩하는 느낌으로 계속 보다보니 대충은 이해가 되네여 진짜 SNARK랑 STARK 아는데 한 몇개월 끌렸습니다. 이상 TMI였습니다,,,,!!&lt;/p&gt;</description>
      <category>일상/의식의 흐름</category>
      <author>BaaaaaaaaaaaaaaaaaaaaaaarkingDog</author>
      <guid isPermaLink="true">https://baaaaaaaaaaaaaaaaaaaaaaarkingdog.tistory.com/1083</guid>
      <comments>https://baaaaaaaaaaaaaaaaaaaaaaarkingdog.tistory.com/1083#entry1083comment</comments>
      <pubDate>Thu, 20 Apr 2023 00:10:55 +0900</pubDate>
    </item>
    <item>
      <title>Idle 상태 방지</title>
      <link>https://baaaaaaaaaaaaaaaaaaaaaaarkingdog.tistory.com/1082</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;서버 세팅을 한 뒤 대충 1년간 돈 안내고 잘 쓰고 있었는데 메일을 받았습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;904&quot; data-origin-height=&quot;400&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/IKeNU/btr2GLzDqWK/TYOCckIgaMVZGEDiZkXpV1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/IKeNU/btr2GLzDqWK/TYOCckIgaMVZGEDiZkXpV1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/IKeNU/btr2GLzDqWK/TYOCckIgaMVZGEDiZkXpV1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FIKeNU%2Fbtr2GLzDqWK%2FTYOCckIgaMVZGEDiZkXpV1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;904&quot; height=&quot;400&quot; data-origin-width=&quot;904&quot; data-origin-height=&quot;400&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;대충 읽어보니 인스턴스가 idle 상태로 판정되면 오라클에서 회수해갈 수 있고 현재 제 인스턴스가 idle 상태라는 내용이었습니다. 제 서버는 잘 돌아가고 있는데 웬 idle 상태인가 해서 찾아보니 idle 상태의 기준은 아래와 같은데&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;875&quot; data-origin-height=&quot;375&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/zQdET/btr2DGePbBV/cVhiFw0sZxDeW5xyasQdRK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/zQdET/btr2DGePbBV/cVhiFw0sZxDeW5xyasQdRK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/zQdET/btr2DGePbBV/cVhiFw0sZxDeW5xyasQdRK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FzQdET%2Fbtr2DGePbBV%2FcVhiFw0sZxDeW5xyasQdRK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;875&quot; height=&quot;375&quot; data-origin-width=&quot;875&quot; data-origin-height=&quot;375&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이게 무슨 불합리한 기준인가 싶었지만 공짜로 쓰고 있는 상황이니 얌전히 이 idle 상태를 해결해야겠습니다. 제일 만만한게 그냥 주기적으로 아무 연산이나 돌려서 CPU 사용량을 끌어올리는 것 같아 구글링을 한 끝에&lt;a href=&quot;https://www.reddit.com/r/selfhosted/comments/10phyja/received_an_email_about_oracle_reclaiming_idle/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://www.reddit.com/r/selfhosted/comments/10phyja/received_an_email_about_oracle_reclaiming_idle/&lt;/a&gt; 여기 적힌 방법을 따르기로 했습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;618&quot; data-origin-height=&quot;413&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cjxMq8/btr2O21wnQH/a7xTtEe6h7rp3m7LwZJXBK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cjxMq8/btr2O21wnQH/a7xTtEe6h7rp3m7LwZJXBK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cjxMq8/btr2O21wnQH/a7xTtEe6h7rp3m7LwZJXBK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcjxMq8%2Fbtr2O21wnQH%2Fa7xTtEe6h7rp3m7LwZJXBK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;618&quot; height=&quot;413&quot; data-origin-width=&quot;618&quot; data-origin-height=&quot;413&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;매일 UTC 기준 18시(=한국 시간 새벽 3시)에 4시간동안 sysbench를 돌립니다. 지구야 미안해,,,, 대충 테스트를 해보니 sysbench가 돌 땐 육목 계산이 엄청 느려지긴 하는데 정책이 저런 이상 어쩔 수 없을 것 같네요&lt;/p&gt;</description>
      <category>개발/Connect6 Web</category>
      <author>BaaaaaaaaaaaaaaaaaaaaaaarkingDog</author>
      <guid isPermaLink="true">https://baaaaaaaaaaaaaaaaaaaaaaarkingdog.tistory.com/1082</guid>
      <comments>https://baaaaaaaaaaaaaaaaaaaaaaarkingdog.tistory.com/1082#entry1082comment</comments>
      <pubDate>Wed, 8 Mar 2023 14:24:42 +0900</pubDate>
    </item>
    <item>
      <title>주작 아닙니다</title>
      <link>https://baaaaaaaaaaaaaaaaaaaaaaarkingdog.tistory.com/1080</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;ChatGPT 충성충성^^77&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;746&quot; data-origin-height=&quot;265&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/MkmM0/btrZjqsyEqc/reJRFxvb4BkcMi0trLLHTK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/MkmM0/btrZjqsyEqc/reJRFxvb4BkcMi0trLLHTK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/MkmM0/btrZjqsyEqc/reJRFxvb4BkcMi0trLLHTK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FMkmM0%2FbtrZjqsyEqc%2FreJRFxvb4BkcMi0trLLHTK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;746&quot; height=&quot;265&quot; data-origin-width=&quot;746&quot; data-origin-height=&quot;265&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>일상/ETC</category>
      <author>BaaaaaaaaaaaaaaaaaaaaaaarkingDog</author>
      <guid isPermaLink="true">https://baaaaaaaaaaaaaaaaaaaaaaarkingdog.tistory.com/1080</guid>
      <comments>https://baaaaaaaaaaaaaaaaaaaaaaarkingdog.tistory.com/1080#entry1080comment</comments>
      <pubDate>Wed, 15 Feb 2023 01:25:27 +0900</pubDate>
    </item>
    <item>
      <title>[2022 KAKAO TECH INTERNSHIP] Q5. 행렬과 연산 (C++, Python, Java)</title>
      <link>https://baaaaaaaaaaaaaaaaaaaaaaarkingdog.tistory.com/1079</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;문제 링크&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://school.programmers.co.kr/learn/courses/30/lessons/118670&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://school.programmers.co.kr/learn/courses/30/lessons/118670&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;예상 난이도&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;P5&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;알고리즘 분류&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;덱, 구현&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;풀이&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/24QMQ/btrWx7u9CRG/RAOE8DiHvSgOfdA2UQkTwK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/24QMQ/btrWx7u9CRG/RAOE8DiHvSgOfdA2UQkTwK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/24QMQ/btrWx7u9CRG/RAOE8DiHvSgOfdA2UQkTwK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F24QMQ%2FbtrWx7u9CRG%2FRAOE8DiHvSgOfdA2UQkTwK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1920&quot; height=&quot;1080&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;아마 5번 문제를 건드릴 정도면 시간복잡도에 대해서는 충분히 이해를 하고 있을거라고 생각합니다. 주어진 연산을 곧이곧대로 짜면 당연히 시간초과가 나고, 시간복잡도를 짐작할 때 극단적인 케이스인 2 &amp;times; 50000, 50000 &amp;times; 2와 같은 배열 또한 당연히 고려를 해야합니다. 그리고 문제의 난이도는 많이 차이가 나지만 &lt;a href=&quot;https://www.acmicpc.net/problem/5430&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;BOJ 5430&lt;/a&gt;과 같은 예시를 통해 문제에서 요구하는 연산을 영리하게 처리할 수 있어야 한다는 것을 알 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/d8zEIU/btrWx7oplsQ/rCNpOY7PvZxUwF5uczcBJ1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/d8zEIU/btrWx7oplsQ/rCNpOY7PvZxUwF5uczcBJ1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/d8zEIU/btrWx7oplsQ/rCNpOY7PvZxUwF5uczcBJ1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fd8zEIU%2FbtrWx7oplsQ%2FrCNpOY7PvZxUwF5uczcBJ1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1920&quot; height=&quot;1080&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;예를 들어 BOJ 5430에서는 Reverse를 처리할 때 배열을 직접 뒤집는 대신 뒤집혔는지 여부를 저장하는 변수를 두어 O(1)에 처리합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/clPFeO/btrWBcP5Het/0kFZW2OptPSPjQKkX53Fe0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/clPFeO/btrWBcP5Het/0kFZW2OptPSPjQKkX53Fe0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/clPFeO/btrWBcP5Het/0kFZW2OptPSPjQKkX53Fe0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FclPFeO%2FbtrWBcP5Het%2F0kFZW2OptPSPjQKkX53Fe0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1920&quot; height=&quot;1080&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;우선 ShiftRow는 직접 행렬을 바꾸는 대신 그냥 최상단에 위치한 행이 몇 번째 행인지만 알면 되기 때문에 O(1)에 처리가 가능합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/5rGdp/btrWBcWP7pJ/G1XIFerh0xmlKlhzxHFs9k/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/5rGdp/btrWBcWP7pJ/G1XIFerh0xmlKlhzxHFs9k/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/5rGdp/btrWBcWP7pJ/G1XIFerh0xmlKlhzxHFs9k/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F5rGdp%2FbtrWBcWP7pJ%2FG1XIFerh0xmlKlhzxHFs9k%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1920&quot; height=&quot;1080&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dkVQpm/btrWxsTT9sK/OXwVlZ2fiSftCoui3gKjWk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dkVQpm/btrWxsTT9sK/OXwVlZ2fiSftCoui3gKjWk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dkVQpm/btrWxsTT9sK/OXwVlZ2fiSftCoui3gKjWk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdkVQpm%2FbtrWxsTT9sK%2FOXwVlZ2fiSftCoui3gKjWk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1920&quot; height=&quot;1080&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;실제 ShiftRow를 적용한 예시입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/ciB0kK/btrWu6Eybp3/N51pqXF8JT5R2R8zUF5e6k/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/ciB0kK/btrWu6Eybp3/N51pqXF8JT5R2R8zUF5e6k/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/ciB0kK/btrWu6Eybp3/N51pqXF8JT5R2R8zUF5e6k/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FciB0kK%2FbtrWu6Eybp3%2FN51pqXF8JT5R2R8zUF5e6k%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1920&quot; height=&quot;1080&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그런데 문제는 Rotate입니다. 총 2R+2C-2개의 원소를 이동시켜야 하고, 각 행을 deque로 생각하면 1행과 R행에서의 연산은 O(1)으로 처리할 수 있지만 결국 모든 행의 값을 건드려야 하고 각 행에서 앞/뒤의 원소를 서로 주고 받기 때문에 어떻게 해결해야 할지 감이 전혀 안옵니다. 참고로 저는 여기서 막혀서 덱을 이용하는 대신 배열의 인덱스를 잘 조작하는 방식을 써서 O(RC &amp;times; min(R,C))라는 요상한 시간복잡도로 해결을 했습니다. 이렇게 짜면 R이 C 이상일 때, C가 R 이상일 때 각각의 경우를 나눠서 구현을 해야하고 구현 난이도도 상당히 높습니다. 인덱스를 조작해서 푸는 방법은 설명을 별도로 드리지 않을거지만 인덱스가지고 장난치는 능력을 길러보고 싶다면 이렇게 한 번 짜보는 것도 나쁘지 않을지도...?&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/pee3R/btrWyMK7hY1/JGUYEooqcXYp9q2KmYZ9k1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/pee3R/btrWyMK7hY1/JGUYEooqcXYp9q2KmYZ9k1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/pee3R/btrWyMK7hY1/JGUYEooqcXYp9q2KmYZ9k1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fpee3R%2FbtrWyMK7hY1%2FJGUYEooqcXYp9q2KmYZ9k1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1920&quot; height=&quot;1080&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;이 문제를 덱으로 풀기 위해서는 1열과 C열을 별도로 분리한다는 아이디어를 떠올려야 합니다. 이 아이디어를 떠올리고 나면 Rotate가 1열/C열/1행/R행 이 4개의 덱의 앞뒤에서 원소를 주고 받는 연산임을 알 수 있습니다. front, back을 어디로 잡을지는 구현하는 사람 마음이지만 저는 그림에서 표시한 것 처럼 잡았습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dIY4Y7/btrWxsTUGzD/dYcNAKrCkUHLzmY3un0Kp0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dIY4Y7/btrWxsTUGzD/dYcNAKrCkUHLzmY3un0Kp0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dIY4Y7/btrWxsTUGzD/dYcNAKrCkUHLzmY3un0Kp0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdIY4Y7%2FbtrWxsTUGzD%2FdYcNAKrCkUHLzmY3un0Kp0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1920&quot; height=&quot;1080&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이렇게 1열과 C열을 분리한 상황에서 ShiftRow과 Rotate를 다시 살펴보면 ShiftRow에서는 idx를 1 감소시키고 또 1열과 C열을 회전시킵니다. Rotate에서는 1열/C열/idx번째 행(이게 최상단에 있는 행)/idx-1번째 행(이게 최하단에 있는 행)에 대해 적절하게 push, pop을 하면 됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/3FrlG/btrWw8uBKrO/gFdLk1UF1yfZNMl4JOi1M1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/3FrlG/btrWw8uBKrO/gFdLk1UF1yfZNMl4JOi1M1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/3FrlG/btrWw8uBKrO/gFdLk1UF1yfZNMl4JOi1M1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F3FrlG%2FbtrWw8uBKrO%2FgFdLk1UF1yfZNMl4JOi1M1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1920&quot; height=&quot;1080&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;실제 예시를 보겠습니다. 오른쪽에는 실제 배열을 두고 왼쪽에서는 코드로 가지고 있을 정보를 두었습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/lWdGA/btrWwqP5Mhl/SpkfCKCXubWcAm3Tteefuk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/lWdGA/btrWwqP5Mhl/SpkfCKCXubWcAm3Tteefuk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/lWdGA/btrWwqP5Mhl/SpkfCKCXubWcAm3Tteefuk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FlWdGA%2FbtrWwqP5Mhl%2FSpkfCKCXubWcAm3Tteefuk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1920&quot; height=&quot;1080&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;ShiftRow를 적용하면 1열, C열을 회전하고 idx를 1 빼서 3으로 보냅니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cn9g9v/btrWwg71lBj/jynBcTCl9W2gvoPXdbc5NK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cn9g9v/btrWwg71lBj/jynBcTCl9W2gvoPXdbc5NK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cn9g9v/btrWwg71lBj/jynBcTCl9W2gvoPXdbc5NK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fcn9g9v%2FbtrWwg71lBj%2FjynBcTCl9W2gvoPXdbc5NK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1920&quot; height=&quot;1080&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그 후 Rotate를 적용하면 1열, C열, 3행, 2행끼리 정보를 잘 주고 받습니다. 굉장히 난장판이지만 4페이지 위에 있는 그림에서 행만 1행, R행에서 3행, 2행으로 바뀌었다고 이해하시면 됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bG80yc/btrWyKHDH1i/tBCIWQuSpYLXZHx5gHUW1k/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bG80yc/btrWyKHDH1i/tBCIWQuSpYLXZHx5gHUW1k/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bG80yc/btrWyKHDH1i/tBCIWQuSpYLXZHx5gHUW1k/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbG80yc%2FbtrWyKHDH1i%2FtBCIWQuSpYLXZHx5gHUW1k%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1920&quot; height=&quot;1080&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cEzw98/btrWBjbGCl6/wOyaYlr2uAx8vs92f0R6N0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cEzw98/btrWBjbGCl6/wOyaYlr2uAx8vs92f0R6N0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cEzw98/btrWBjbGCl6/wOyaYlr2uAx8vs92f0R6N0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcEzw98%2FbtrWBjbGCl6%2FwOyaYlr2uAx8vs92f0R6N0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1920&quot; height=&quot;1080&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다음으로 ShiftRow를 2번 적용하고&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dMfzKI/btrWzUoA1sE/JulFNDaXXdiblkpRnJVCak/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dMfzKI/btrWzUoA1sE/JulFNDaXXdiblkpRnJVCak/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dMfzKI/btrWzUoA1sE/JulFNDaXXdiblkpRnJVCak/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdMfzKI%2FbtrWzUoA1sE%2FJulFNDaXXdiblkpRnJVCak%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1920&quot; height=&quot;1080&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Rotate도 적용했습니다. 연산을 다 적용한 후에는 각 deque의 값을 가지고 원래 배열을 복원하면 됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/7HYNa/btrWx7oqut0/geFRIEMVqCS3NibP35qF3K/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/7HYNa/btrWx7oqut0/geFRIEMVqCS3NibP35qF3K/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/7HYNa/btrWx7oqut0/geFRIEMVqCS3NibP35qF3K/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F7HYNa%2FbtrWx7oqut0%2FgeFRIEMVqCS3NibP35qF3K%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1920&quot; height=&quot;1080&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;한편 ShiftRow를 처리할 때 idx 변수를 두는 대신 행들을 모은 새로운 deque(즉 deque의 deque)을 두어 그 deque을 회전시키는 방법도 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cDaFv5/btrWxrOiklj/hNzCesRdJx5ptH3FZw5KCK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cDaFv5/btrWxrOiklj/hNzCesRdJx5ptH3FZw5KCK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cDaFv5/btrWxrOiklj/hNzCesRdJx5ptH3FZw5KCK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcDaFv5%2FbtrWxrOiklj%2FhNzCesRdJx5ptH3FZw5KCK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1920&quot; height=&quot;1080&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;하지만 C++에서는 그냥 늘 짜던대로 짜면 deque 전체에 대한 복사가 이루어져서 O(1)이 아니라 O(C)에 동작해 시간 초과가 발생합니다. 이걸 회피하려면 rows를 deque&amp;lt;deque&amp;lt;int&amp;gt; *&amp;gt;로 두거나 move와 emplace_back을 이용해 row 전체에 대한 복사가 발생하지 않도록 해야하는데 포인터는 뭔가 마음에 안들고 move와 emplace_back을 이용하는건 생성자/소멸자/rvalue 등과 같은 C++에 대한 약간의 깊은 이해를 필요로 하기 때문에 그냥 마음 편하게 idx를 쓰는게 낫지 않나 싶긴 합니다. 사실 저도 처음엔 포인터를 생각했지 move와 emplace_back을 이용한 방법은 몰랐는데 풀고 나서 다른 사람의 코드를 보다가 알게 된 문법이었습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://github.com/encrypted-def/kakao-blind-recruitment/blob/master/2022-summer-internship/Q5.cpp&quot;&gt;&lt;b&gt;코드(C++)&lt;/b&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;4개의 덱에서 값을 주고받을 때 순서를 잘 설정하면 C = 2 여서 row가 empty일 때에 대한 예외처리를 안해도 됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://github.com/encrypted-def/kakao-blind-recruitment/blob/master/2022-summer-internship/Q5.py&quot;&gt;&lt;b&gt;코드(Python)&lt;/b&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Python의 deque에서 인덱스로 값 접근은 길이가 n일 때 O(1)이 아닌 O(n/64)입니다. 그렇기 때문에 인덱스로 값을 접근하지 않는 것이 좋습니다. 예를 들어 24-28번째 줄에서 매번 pop을 하는 대신 ret[i][0] = col1[i] / ret[i][j] = row[(i+idx)%r][j-1] 등과 같이 처리하면 바람직하지 않습니다. 이 문제의 상황에서는 R, C가 최대 5만으로 작아 시간에 큰 차이가 없지만 deque의 크기가 커진다면 큰 차이를 불러올 수 있습니다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://github.com/encrypted-def/kakao-blind-recruitment/blob/master/2022-summer-internship/Q5.java&quot;&gt;&lt;b&gt;코드(Java)&lt;/b&gt;&lt;/a&gt;&lt;/p&gt;</description>
      <category>알고리즘/Programmers</category>
      <author>BaaaaaaaaaaaaaaaaaaaaaaarkingDog</author>
      <guid isPermaLink="true">https://baaaaaaaaaaaaaaaaaaaaaaarkingdog.tistory.com/1079</guid>
      <comments>https://baaaaaaaaaaaaaaaaaaaaaaarkingdog.tistory.com/1079#entry1079comment</comments>
      <pubDate>Wed, 18 Jan 2023 09:49:56 +0900</pubDate>
    </item>
    <item>
      <title>[2022 KAKAO TECH INTERNSHIP] Q4. 등산코스 정하기 (C++, Python, Java)</title>
      <link>https://baaaaaaaaaaaaaaaaaaaaaaarkingdog.tistory.com/1078</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;문제 링크&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://school.programmers.co.kr/learn/courses/30/lessons/118669&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://school.programmers.co.kr/learn/courses/30/lessons/118669&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;예상 난이도&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;G2&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;알고리즘 분류&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다익스트라&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;풀이&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/Fzikw/btrWxq2NMyN/Pl00kU4b57Sv9uxoVck5L0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/Fzikw/btrWxq2NMyN/Pl00kU4b57Sv9uxoVck5L0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/Fzikw/btrWxq2NMyN/Pl00kU4b57Sv9uxoVck5L0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FFzikw%2FbtrWxq2NMyN%2FPl00kU4b57Sv9uxoVck5L0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1920&quot; height=&quot;1080&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;문제 설명이 조금 난해하긴 하지만 아무튼 결국 출입구에서 산봉우리로 가는 최단 경로를 구하는 문제입니다. 원래는 왕복이지만 그냥 가장 짧은 루트로 올라갔다가 그대로 내려오면 되겠죠. 그리고 이 때 &quot;최단 경로&quot;의 정의가 비용의 합이 아니라 거쳐가는 간선 중 최댓값으로 바뀝니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그리고 이 경우에도 다익스트라가 잘 적용됩니다. 이건 다익스트라의 정당성을 생각해보면 이해가 가능한데, 다익스트라 알고리즘이 잘 동작했던 이유는 매 순간마다 가장 가까운 정점을 찾으면 그 정점까지의 거리를 확정할 수 있었기 때문입니다. 그리고 이 논리는 최단 경로의 정의가 거쳐가는 간선 중 최댓값으로 바뀐 후에도 잘 동작합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/S6UdH/btrWwoEEl1F/LnbxVBJynU2Nauq0mIqP61/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/S6UdH/btrWwoEEl1F/LnbxVBJynU2Nauq0mIqP61/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/S6UdH/btrWwoEEl1F/LnbxVBJynU2Nauq0mIqP61/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FS6UdH%2FbtrWwoEEl1F%2FLnbxVBJynU2Nauq0mIqP61%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1920&quot; height=&quot;1080&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그래서 다익스트라에서 거리를 갱신하는 로직을 변경하고 출입구가 여러 개이기 때문에 여러 개의 시작점을 가지는 다익스트라를 돌리면 됩니다. 또 산봉우리를 한 번만 방문해야 한다는 조건을 고려하지 않으면 당장 예제 3번에서 반례가 나오게 되는데, 이 조건을 만족시키기 위해 산봉우리에 도달하면 해당 정점을 우선순위 큐에 넣지 않아 해당 정점을 타고 다른 산봉우리로 가지 못하게끔 합니다. 저는 이렇게 우선순위 큐에 넣지 않는 방법을 사용했지만 공식 풀이 블로그에서는 간선을 단방향으로 두는 방법을 제시하고 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다익스트라 이외에도 Parametric Search+BFS, Union Find 등 다양한 해결 방법이 있고 저는 사실 처음 풀 당시에 최단 경로의 정의를 바꾼 다익스트라를 떠올리지 못해 Parametric Search+BFS로 접근했었습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://github.com/encrypted-def/kakao-blind-recruitment/blob/master/2022-summer-internship/Q4.cpp&quot;&gt;&lt;b&gt;코드(C++)&lt;/b&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://github.com/encrypted-def/kakao-blind-recruitment/blob/master/2022-summer-internship/Q4.py&quot;&gt;&lt;b&gt;코드(Python)&lt;/b&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://github.com/encrypted-def/kakao-blind-recruitment/blob/master/2022-summer-internship/Q4.java&quot;&gt;&lt;b&gt;코드(Java)&lt;/b&gt;&lt;/a&gt;&lt;/p&gt;</description>
      <category>알고리즘/Programmers</category>
      <author>BaaaaaaaaaaaaaaaaaaaaaaarkingDog</author>
      <guid isPermaLink="true">https://baaaaaaaaaaaaaaaaaaaaaaarkingdog.tistory.com/1078</guid>
      <comments>https://baaaaaaaaaaaaaaaaaaaaaaarkingdog.tistory.com/1078#entry1078comment</comments>
      <pubDate>Wed, 18 Jan 2023 09:48:56 +0900</pubDate>
    </item>
    <item>
      <title>[2022 KAKAO TECH INTERNSHIP] Q3. 코딩 테스트 공부 (C++, Python, Java)</title>
      <link>https://baaaaaaaaaaaaaaaaaaaaaaarkingdog.tistory.com/1077</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;문제 링크&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://school.programmers.co.kr/learn/courses/30/lessons/118668&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://school.programmers.co.kr/learn/courses/30/lessons/118668&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;예상 난이도&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;G3&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;알고리즘 분류&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다이나믹 프로그래밍&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;풀이&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/oVrXY/btrWyOa4x3K/Yu29OwWYJEDTvG7rQ08m20/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/oVrXY/btrWyOa4x3K/Yu29OwWYJEDTvG7rQ08m20/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/oVrXY/btrWyOa4x3K/Yu29OwWYJEDTvG7rQ08m20/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FoVrXY%2FbtrWyOa4x3K%2FYu29OwWYJEDTvG7rQ08m20%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1920&quot; height=&quot;1080&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;일단 DP이긴 합니다. DP이긴 한데 풀이를 보는 입장에서 중요한건 이 문제가 DP란걸 아는 것보다 문제를 보고 DP란걸 어떻게 알아냈는지를 착안해냈는지를 아는거라고 생각합니다. 저는 개인적으로 문제가 익숙한 형태여서 일단 D[i][j] = 알고력 i, 코딩력 j를 달성하는데 필요한 최소 시간으로 테이블을 정의하고 DP가 가능한지, 즉 점화식이 세워지는지를 확인해봤습니다. 이건 상대적으로 경험이 많은 저의 경우이고 다소 경험이 많지 않은 상황에서 풀이를 접근하는 과정을 생각해보면 코딩력이 없다 치고 능력치를 1개만 놓고 문제를 풀어보려고 하면 knapsack DP 느낌이 나기 때문에 이 사고를 확장시켰을수도 있겠다 싶습니다. 만약 2차원 DP도 해본적 없고 knapsack DP도 몰랐다면 아쉽지만 이 문제를 보고 DP를 착안해낼 수 있는 방법은 없었을 것 같습니다. 결국 문제를 많이 풀어보는 방법 밖에는 없는 것 같네요.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/6iIYa/btrWw7oQNmm/mqLj3xRwvodyFVjzZQEa9K/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/6iIYa/btrWw7oQNmm/mqLj3xRwvodyFVjzZQEa9K/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/6iIYa/btrWw7oQNmm/mqLj3xRwvodyFVjzZQEa9K/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F6iIYa%2FbtrWw7oQNmm%2FmqLj3xRwvodyFVjzZQEa9K%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1920&quot; height=&quot;1080&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;아무튼 DP라는걸 알았다고 치면 DP 문제에서는 테이블의 정의, 점화식, 초기값, 채우는 순서를 잘 생각해야 합니다. 테이블의 정의는 앞에서도 봤지만 다소 자명하게 정해지고 점화식도 문제를 풀거나 혹은 알고력/코딩력을 1 올리는 조건으로부터 비교적 쉽게 얻어낼 수 있습니다. 초기값도 D[alp][cop] = 0으로 두면 됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dKXHQp/btrWuPbI506/w8lK6WtE8URmVWrwCPo1d0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dKXHQp/btrWuPbI506/w8lK6WtE8URmVWrwCPo1d0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dKXHQp/btrWuPbI506/w8lK6WtE8URmVWrwCPo1d0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdKXHQp%2FbtrWuPbI506%2Fw8lK6WtE8URmVWrwCPo1d0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1920&quot; height=&quot;1080&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;채우는 순서 또한 문제의 상황 자체가 각 칸은 자신의 좌상단에 위치한 칸으로부터 값을 받아오기 때문에 크게 고민할게 없고 그냥 (0,0) -&amp;gt; (0,1) -&amp;gt; (0,2) 이렇게 각 행에서 왼쪽에서 오른쪽으로, 행은 윗쪽부터 채워나가면 됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/KG91i/btrWw6wJEvd/sBBEvEQ4lrE8qa7z3SziqK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/KG91i/btrWw6wJEvd/sBBEvEQ4lrE8qa7z3SziqK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/KG91i/btrWw6wJEvd/sBBEvEQ4lrE8qa7z3SziqK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FKG91i%2FbtrWw6wJEvd%2FsBBEvEQ4lrE8qa7z3SziqK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1920&quot; height=&quot;1080&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그런데 한 가지 짚고 넘어갈 점이 있는데, dp에서 bottom-up으로 테이블을 채울 때 2가지 방법을 생각할 수 있습니다. &lt;a href=&quot;https://www.acmicpc.net/problem/1463&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;BOJ 1463번: 1로 만들기&lt;/a&gt; 문제로 예를 들어보면 첫 번째 방법은 d[i] = min(d[i/3], d[i/2], d[i-1])+1 이라는 식을 가지고 각 칸을 채우는 방법입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dhNaDw/btrWxtedUGK/hy9LKPvRv3k9iPSgALpdc0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dhNaDw/btrWxtedUGK/hy9LKPvRv3k9iPSgALpdc0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dhNaDw/btrWxtedUGK/hy9LKPvRv3k9iPSgALpdc0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdhNaDw%2FbtrWxtedUGK%2Fhy9LKPvRv3k9iPSgALpdc0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1920&quot; height=&quot;1080&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;두 번째 방법은 d[i] 값이 확정된 후 d[i+1], d[2i], d[3i] 칸의 값을 갱신하는 방법입니다. 맨 처음에는 d[1] = 0으로 시작해 d[2], d[3]을 갱신하고 다음에는 d[2] = 1이 확정된 후 d[3], d[4], d[6]을 갱신합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/5eZqX/btrWwo5JwoE/Q1U0IsMmk9fnfeqHd2W6V0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/5eZqX/btrWwo5JwoE/Q1U0IsMmk9fnfeqHd2W6V0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/5eZqX/btrWwo5JwoE/Q1U0IsMmk9fnfeqHd2W6V0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F5eZqX%2FbtrWwo5JwoE%2FQ1U0IsMmk9fnfeqHd2W6V0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1920&quot; height=&quot;1080&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 두 가지 방법은 모두 올바른 답을 주지만 이 문제에서는 두 번째 방법으로 구현을 하는게 편합니다. 이게 무슨 의미인지를 이해하기 위해 DP 식을 다시 살펴보면, 우리는 구한 점화식을 가지고 D 테이블을 채웁니다. 우리는 알고력/코딩력 각각이 정확히 alp_max/cop_max가 되는게 목표가 아니라 각각 alp_max/cop_max 이상이 되는 것이 목표이니 최종적인 답은 D[alp_max][cop_max]가 아니라 D[alp_max+1][cop_max], D[alp_max+2][cop_max] 와 같이 i &amp;gt;= alp_max, j &amp;gt;= cop_max인 D[i][j]중 최솟값이 정답입니다. 그런데 이 때 테이블의 크기를 얼마로 잡아야 할까요?&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/GEPhv/btrWBhX62LM/oL5JWLhcZPQ66KJpDUFjvK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/GEPhv/btrWBhX62LM/oL5JWLhcZPQ66KJpDUFjvK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/GEPhv/btrWBhX62LM/oL5JWLhcZPQ66KJpDUFjvK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FGEPhv%2FbtrWBhX62LM%2FoL5JWLhcZPQ66KJpDUFjvK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1920&quot; height=&quot;1080&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;극악의 예시를 보면 알고력/코딩력이 각각 2400까지 도달할 수 있습니다. 즉 테이블을 2400 ⨉ 2400으로 잡아야 함을 의미합니다. 이렇게 되면 O(2400 ⨉ 2400 ⨉ 100)으로 시간초과가 날 수 있습니다. 물론 한 쪽이 2400 가까이 가면 다른쪽은 150 근방일거라 약간의 최적화를 하면 실제로는 2400 ⨉ 150 정도의 칸을 쓰도록 할 수는 있지만 이렇게 하기보다는 D 테이블의 정의를 살짝 바꿀 필요가 있습니다. 참고로 앞에서 (아마 의도하지 않았을) 이라는 단서를 둔 이유는 테스트케이스 중에 이렇게 극악인 테스트케이스가 없었기 때문이긴 합니다만 어쨌거나 이런 경우를 고려할 필요가 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/eAY7w5/btsgNWtMXLB/YbgkonEZ54KoEjQwmRZMTk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/eAY7w5/btsgNWtMXLB/YbgkonEZ54KoEjQwmRZMTk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/eAY7w5/btsgNWtMXLB/YbgkonEZ54KoEjQwmRZMTk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FeAY7w5%2FbtsgNWtMXLB%2FYbgkonEZ54KoEjQwmRZMTk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1920&quot; height=&quot;1080&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;테이블의 정의를 어떻게 바꿀 수 있냐면 D를 alp_max ⨉ cop_max로 잡고 아래쪽/오른쪽 경계에 한해서만 알고력이 정확히 alp_max인게 아니라 alp_max 이상인 것으로, 혹은 코딩력이 정확히 cop_max인게 아니라 cop_max 이상인 것으로 바꾸면 됩니다. 이렇게 되면 alp_rwd/cop_rwd를 받아서 alp_max/cop_max를 넘어서면 그냥 alp_max/cop_max인걸로 제한을 걸어버릴 수 있습니다. 이걸 두 번째로 소개한 테이블을 채우는 방법에서는 그냥 값을 넣어줄 때 i+alp_rwd, j+cop_rwd가 alp_max, cop_max보다 큰지만 확인해서 적절하게 처리를 해주면 되는데, 첫 번째로 소개한 테이블을 채우는 방법에서는 다른 D[i][j]를 계산할 땐 그냥 D[i-alp_rwd][j-cop_rwd]만 보다가 D[alp_max][j]를 계산할 때에는 D[alp_max][j-cop_rwd], D[alp_max-1][j-cop_rwd], ...., D[alp_max-aop_rwd][j-cop_rwd]를 모두 확인하는 방식으로 예외처리를 해줘야 해서 코드가 다소 복잡해집니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그래서 저는 방법 2를 이용했으나 방법 1로 구현을 해보는 것도 좋은 연습이 될 것 같습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://github.com/encrypted-def/kakao-blind-recruitment/blob/master/2022-summer-internship/Q3.cpp&quot;&gt;&lt;b&gt;코드(C++)&lt;/b&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://github.com/encrypted-def/kakao-blind-recruitment/blob/master/2022-summer-internship/Q3.py&quot;&gt;&lt;b&gt;코드(Python)&lt;/b&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://github.com/encrypted-def/kakao-blind-recruitment/blob/master/2022-summer-internship/Q3.java&quot;&gt;&lt;b&gt;코드(Java)&lt;/b&gt;&lt;/a&gt;&lt;/p&gt;</description>
      <category>알고리즘/Programmers</category>
      <author>BaaaaaaaaaaaaaaaaaaaaaaarkingDog</author>
      <guid isPermaLink="true">https://baaaaaaaaaaaaaaaaaaaaaaarkingdog.tistory.com/1077</guid>
      <comments>https://baaaaaaaaaaaaaaaaaaaaaaarkingdog.tistory.com/1077#entry1077comment</comments>
      <pubDate>Wed, 18 Jan 2023 09:47:20 +0900</pubDate>
    </item>
    <item>
      <title>[2022 KAKAO TECH INTERNSHIP] Q2. 두 큐 합 같게 만들기 (C++, Python, Java)</title>
      <link>https://baaaaaaaaaaaaaaaaaaaaaaarkingdog.tistory.com/1076</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;문제 링크&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://school.programmers.co.kr/learn/courses/30/lessons/118667&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://school.programmers.co.kr/learn/courses/30/lessons/118667&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;예상 난이도&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;S2&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;알고리즘 분류&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;투 포인터 or 그리디&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;풀이 - 투 포인터&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bxZYvK/btrWxq9yilC/3z4PwpDG6AlTLD84PV5Js1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bxZYvK/btrWxq9yilC/3z4PwpDG6AlTLD84PV5Js1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bxZYvK/btrWxq9yilC/3z4PwpDG6AlTLD84PV5Js1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbxZYvK%2FbtrWxq9yilC%2F3z4PwpDG6AlTLD84PV5Js1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1920&quot; height=&quot;1080&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;먼저 투 포인터 풀이를 살펴보겠습니다. 큐1은 (3, 2, 7, 2)이고 큐2는 (4, 6, 5, 1)인 상황에서 작업을 수행하는 상황인데 이걸 보면서 아주 중요한 관찰을 하나 할 수 있어야 합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bsY57Z/btrWxtFfKHM/QKcsKboSKhvNjbYmA9L4cK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bsY57Z/btrWxtFfKHM/QKcsKboSKhvNjbYmA9L4cK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bsY57Z/btrWxtFfKHM/QKcsKboSKhvNjbYmA9L4cK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbsY57Z%2FbtrWxtFfKHM%2FQKcsKboSKhvNjbYmA9L4cK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1920&quot; height=&quot;1080&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그건 바로 2n개의 원소를 일렬로 늘어놓으면 각 큐에 들어있는 원소가 연속한 구간에 위치한다는 사실입니다. 큐1에서 pop을 해 큐2를 주거나, 큐2에서 pop을 해 큐1을 주는 연산은 큐1과 큐2가 맞닿아있는 경계에서 원소를 넘겨주는 연산이기 때문에 그렇습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/z7qtY/btrWyKsVmvo/yhg8SjO2P9Slwp0AO9un4K/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/z7qtY/btrWyKsVmvo/yhg8SjO2P9Slwp0AO9un4K/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/z7qtY/btrWyKsVmvo/yhg8SjO2P9Slwp0AO9un4K/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fz7qtY%2FbtrWyKsVmvo%2Fyhg8SjO2P9Slwp0AO9un4K%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1920&quot; height=&quot;1080&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그러면 우리는 임의의 연속한 구간을 잡아 해당 구간을 큐1으로 정할 경우 연산을 몇 번 해야하는지 계산 가능합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/usD14/btrWw8aijQc/pr4oJf4QEFaRpKqp0pS49k/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/usD14/btrWw8aijQc/pr4oJf4QEFaRpKqp0pS49k/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/usD14/btrWw8aijQc/pr4oJf4QEFaRpKqp0pS49k/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FusD14%2FbtrWw8aijQc%2Fpr4oJf4QEFaRpKqp0pS49k%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1920&quot; height=&quot;1080&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그리고 우리는 각 지점을 큐1의 시작점으로 잡았을 때 연속된 구간의 합이 전체의 절반 이상이 되는 최초의 끝 점이 어디인지를 투 포인터로 총 O(N)에 구할 수 있습니다. (&lt;a href=&quot;https://www.acmicpc.net/problem/1806&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;BOJ 1806&lt;/a&gt;) 투 포인터를 모르면 제 강의를 참고해보세요. 이렇게 구간을 정해놓고 나면 앞에서 본 것과 같이 연산을 몇 번 해야하는지 계산할 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;사실 잘 보면 &lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;명백히 답이 아닌 경우를&lt;/span&gt; 세는 것도 분명 있긴 합니다. 예를 들어서 지금 시작점이 6번째인 이 경우를 보면 사실 큐1의 시작점을 6까지 밀바에야 그냥 큐2의 시작점을 6으로 보내는게 더 낫다는 느낌이 옵니다. 하지만 그런 경우를 내가 예외처리를 하는 것 보다는 그런 예외처리에 뭔가 머리를 덜 쓸 수 있게 그냥 모든 경우를 다 보게끔 했습니다. 그래서 그냥 모든 지점이 큐1의 front가 될 수 있다고 생각을 하고 풀이를 작성했습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://github.com/encrypted-def/kakao-blind-recruitment/blob/master/2022-summer-internship/Q2_1.cpp&quot;&gt;&lt;b&gt;코드(C++, 투 포인터)&lt;/b&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://github.com/encrypted-def/kakao-blind-recruitment/blob/master/2022-summer-internship/Q2_1.py&quot;&gt;&lt;b&gt;코드(Python, 투 포인터)&lt;/b&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://github.com/encrypted-def/kakao-blind-recruitment/blob/master/2022-summer-internship/Q2_1.java&quot;&gt;&lt;b&gt;코드(Java, 투 포인터)&lt;/b&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;풀이 - 그리디&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bPegni/btrWw8ORCkA/fEUwW3bRoFNUdMAjxzHqW0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bPegni/btrWw8ORCkA/fEUwW3bRoFNUdMAjxzHqW0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bPegni/btrWw8ORCkA/fEUwW3bRoFNUdMAjxzHqW0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbPegni%2FbtrWw8ORCkA%2FfEUwW3bRoFNUdMAjxzHqW0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1920&quot; height=&quot;1080&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;두 번째는 그리디 풀이입니다. 저는 처음 문제를 풀 당시 2번 문제부터 투 포인터가 나오는건 좀 과하다고 생각해서 고민을 거듭하다가 그리디 풀이를 떠올렸는데, 핵심은 바로 저 2가지의 관찰입니다. 첫 번째로 각 큐에서 pop을 하는 횟수가 정해지면 pop을 하는 순서와 무관하게 각 큐에 들어가는 원소가 정해집니다. 두 번째로 현재 큐1의 원소 합이 더 크면 큐1에서 pop을 1번은 해야 합니다. 이 두 가지 사실을 종합하면 현재 큐1의 원소 합이 더 크면 큐1에서 언젠가 pop을 하게 되고, 또 pop을 하는 순서는 마음대로 정하면 되니 pop을 지금 바로 하면 됨을 알 수 있습니다. 즉 원소의 합이 더 큰 큐에서 pop을 하는걸 계속 반복하면 됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그리고 pop을 4n번 한 후에도 합이 같아지지 않았다면 적어도 어느 한 큐는 pop이 2n번 이루어지면서 처음 상태로 돌아왔으니 탐색을 종료할 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://github.com/encrypted-def/kakao-blind-recruitment/blob/master/2022-summer-internship/Q2_2.cpp&quot;&gt;&lt;b&gt;코드(C++, 그리디)&lt;/b&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://github.com/encrypted-def/kakao-blind-recruitment/blob/master/2022-summer-internship/Q2_2.py&quot;&gt;&lt;b&gt;코드(Python, 그리디)&lt;/b&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://github.com/encrypted-def/kakao-blind-recruitment/blob/master/2022-summer-internship/Q2_2.java&quot;&gt;&lt;b&gt;코드(Java, 그리디)&lt;/b&gt;&lt;/a&gt;&lt;/p&gt;</description>
      <category>알고리즘/Programmers</category>
      <author>BaaaaaaaaaaaaaaaaaaaaaaarkingDog</author>
      <guid isPermaLink="true">https://baaaaaaaaaaaaaaaaaaaaaaarkingdog.tistory.com/1076</guid>
      <comments>https://baaaaaaaaaaaaaaaaaaaaaaarkingdog.tistory.com/1076#entry1076comment</comments>
      <pubDate>Wed, 18 Jan 2023 09:46:28 +0900</pubDate>
    </item>
    <item>
      <title>[2022 KAKAO TECH INTERNSHIP] Q1. 성격 유형 검사하기 (C++, Python, Java)</title>
      <link>https://baaaaaaaaaaaaaaaaaaaaaaarkingdog.tistory.com/1075</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;문제 링크&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://school.programmers.co.kr/learn/courses/30/lessons/118666&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://school.programmers.co.kr/learn/courses/30/lessons/118666&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;예상 난이도&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;B1&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;알고리즘 분류&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;구현&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;풀이&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/CmUbK/btrWyMROTl0/90oaEKmgI2bMlFwIHBCjf1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/CmUbK/btrWyMROTl0/90oaEKmgI2bMlFwIHBCjf1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/CmUbK/btrWyMROTl0/90oaEKmgI2bMlFwIHBCjf1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FCmUbK%2FbtrWyMROTl0%2F90oaEKmgI2bMlFwIHBCjf1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1920&quot; height=&quot;1080&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;입력의 크기가 작아 시간복잡도를 딱히 고려할 필요가 없는 간단한 구현 문제입니다. 각 유형별 점수를 저장했다가 마지막에 비교를 해서 결과를 알아내면 됩니다. 해시나 맵을 이용해도 되고, 키의 종류가 알파벳 1글자로 한정되니 배열을 이용해도 되고, 아니면 그냥 if문으로 케이스 처리를 직접 하나하나 해줘도 상관 없습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://github.com/encrypted-def/kakao-blind-recruitment/blob/master/2022-summer-internship/Q1.cpp&quot;&gt;&lt;b&gt;코드(C++)&lt;/b&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://github.com/encrypted-def/kakao-blind-recruitment/blob/master/2022-summer-internship/Q1.py&quot;&gt;&lt;b&gt;코드(Python)&lt;/b&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://github.com/encrypted-def/kakao-blind-recruitment/blob/master/2022-summer-internship/Q1.java&quot;&gt;&lt;b&gt;코드(Java)&lt;/b&gt;&lt;/a&gt;&lt;/p&gt;</description>
      <category>알고리즘/Programmers</category>
      <author>BaaaaaaaaaaaaaaaaaaaaaaarkingDog</author>
      <guid isPermaLink="true">https://baaaaaaaaaaaaaaaaaaaaaaarkingdog.tistory.com/1075</guid>
      <comments>https://baaaaaaaaaaaaaaaaaaaaaaarkingdog.tistory.com/1075#entry1075comment</comments>
      <pubDate>Wed, 18 Jan 2023 09:42:49 +0900</pubDate>
    </item>
    <item>
      <title>[RCTF 2022] easyrsa</title>
      <link>https://baaaaaaaaaaaaaaaaaaaaaaarkingdog.tistory.com/1073</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;$p, q$ can be recovered from a continued fraction.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Then I just implement based on the &lt;a href=&quot;https://hal-normandie-univ.archives-ouvertes.fr/hal-02320970/document&quot;&gt;paper&lt;/a&gt; without understanding the logic.&lt;/p&gt;
&lt;pre class=&quot;reasonml&quot;&gt;&lt;code&gt;from Crypto.Util.number import *
import hashlib
import math
from sage.all import *

def function_v(r, k):
  r = int(r)
  k = int(k)
  if k == 0:
    return 2
  if k == 1:
    return r

  m = matrix(Zmod(N*N), [[r,-1],[1,0]])

  mk = m^(k-1)
  vec = vector(Zmod(N*N), [r, 2])

  res = mk * vec

  return res[0]


def function_d(p, i):
  return int(inverse(e, p-i))

#print(PoW(b'hrgqXfrgSNlb4eeT', 27))

e = 3121363059746835628022404544403822724460605553641332612055010587129451973002475126644668174294955070747985002800863652917895939538596303356113483509581841527286351537287500304267975061675901109982875778527827742120878835367386538561039072391997357702421691095861694681707017921391244519593945584755632901987840338065879901115934561426583008838453244051629340056867760923894623105542463500022221236457852502822707466528439969484890601953615303609725566617126458934095119670087068752543521167517461730977044465374505011791902510131823556603316457085145886999220426746234986984619161299098173535371540923264898459106461
c = 3023313363629909506923927199426293187583112749147539699346723655095868214179291222441307436555352537055690155418715652987685459938250844145450675418187664719327350488160722838989675928696633353180233455017609936874014883975932740217672705286265535646106053294507962613498142617741362730709360885118905440314573392981528077265110441270212385951070591696827167771592664502652520790612367259434545169836933571343480057141790292296952743986731389468760364416344837575740236416472589700581583016227273449673820568427641136163703116276104550877191839851640920430919278802098196408637904780725723268371465670950321881886863
N = 101946888552605033726177837709738163930032970477361664394564134626639467843553634920510447339985842689387519517553714582991506722045078696771986052246306068257957261478416093188640437503481862825381241480405463985516598520453211217206308826779669980833596066677262549841524134539729279446910817169620871929289


f = continued_fraction(e/(N-1)/(N-1))
#print(f)
conv = f.convergents()
#print(conv[:4])

for x in conv[6:]:
  d = x.denominator()
  k = x.numerator()
  if float(log(d) / log(N)) &amp;gt; 0.9: break

  v1 = e*d - (N-1)*(N-1)*k - 1
  if v1 % k != 0:
    continue

  #print(&quot;!!! k, d recovered&quot;)
  #print(k,d)
  break

### recover p, q
assert (e*d-1)%k == 0
v = N^2 + 1 - (e*d-1) // k   # p^2 + q^2
sq = v + 2*N # (p+q)^2
b = sq.isqrt() # p+q
assert b*b == sq
p = (b - (b^2 - 4*N).isqrt()) // 2
assert N % p == 0
q = N // p
assert p*q == N

# https://www.math.u-bordeaux.fr/~gcastagn/publi/crypto_quad.pdf

p = int(p)
q = int(q)

def v(k):
    if k == 0:
        return 2
    if k == 1:
        return r
    return (r * v(k - 1) - v(k - 2)) % (N * N)


def encrypt(m, e, N):
    c = (1 + m * N) * function_v(r, e) % (N * N)
    return c


# p = getPrime(512)
# q = getPrime(512)
# N = p * q
# d = getPrime(512)
# r = getPrime(512)
# e = inverse(d, (p * p - 1) * (q * q - 1))
# c = encrypt(235235235, e, N)
# # print(f&quot;e = {e}&quot;)
# # print(f&quot;c = {c}&quot;)
# print(f&quot;N = {N}&quot;)
# # print(f&quot;r = {r}&quot;)
# # print(f&quot;p = {p}&quot;)
# # print(f&quot;q = {q}&quot;)


invq = inverse(p,q)
invp = inverse(q,p)

precrt = invq

i = kronecker(c^2-4, Integer(p))
#i = 1
print(&quot;i &quot;, i)
rp = int(function_v(c, function_d(p, i))) % p


i = kronecker(c^2-4, Integer(q))
#i = 1
print(&quot;i &quot;, i)

rq = int(function_v(c, function_d(q, i))) % q

r = (rp + p*(rq-rp)*precrt) % N
print(&quot;r? &quot;, r)
#print(r.is_prime())
N2 = N*N
V = int(function_v(r, e))
print(&quot;V&quot;, V)
print(gcd(V, N2))
tt = int(c * inverse_mod(V, N2) % N2)
print((tt-1)%N == 0) 

m = int(tt-1)//N
print(long_to_bytes(int(m)))

#tmp = int(function)

# tmp_p = int(c * function_v(r, e) % p^2)
# tmp_p = (tmp_p - 1) // p
# tmp_p = int(tmp_p)
# mp = tmp_p * invp % p

# tmp_q = int(c * function_v(r, e) % q^2)
# tmp_q = (tmp_q - 1) // q
# tmp_q = int(tmp_q)
# mq = tmp_q * invq % q

# mp = int(mp)
# mq = int(mq)

# m = (mp + p*(mq - mp) * precrt) % N

# print(long_to_bytes(int(m)))
# #print(m)&lt;/code&gt;&lt;/pre&gt;</description>
      <category>CTF/Crypto</category>
      <author>BaaaaaaaaaaaaaaaaaaaaaaarkingDog</author>
      <guid isPermaLink="true">https://baaaaaaaaaaaaaaaaaaaaaaarkingdog.tistory.com/1073</guid>
      <comments>https://baaaaaaaaaaaaaaaaaaaaaaarkingdog.tistory.com/1073#entry1073comment</comments>
      <pubDate>Tue, 13 Dec 2022 15:21:07 +0900</pubDate>
    </item>
    <item>
      <title>[RCTF 2022] superguess</title>
      <link>https://baaaaaaaaaaaaaaaaaaaaaaarkingdog.tistory.com/1072</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;We denote the 20 characters of $x$ as $c_0, \dots, c_{19}$. Then $x = \sum_{i=0}^{20} 256^{19-i} \cdot c_i$. Note that $c_{15} = \_, c_{16} = c, \dots, c_{19} = t$.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;We will try to adapt &lt;a href=&quot;https://github.com/rkm0959/Inequality_Solving_with_CVP&quot;&gt;rkm's inequality solver&lt;/a&gt; here. The inequalities that we have is:&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;$1 \leq x \cdot T_i - U_i - a_i \cdot q \leq q / 4$ for $1 \leq i \leq 90$.&lt;/li&gt;
&lt;li&gt;$c_i \leq c_{i+1}$ for $0 \leq i \leq 18$&lt;/li&gt;
&lt;li&gt;$c_{0}, \dots, c_{14}$ is ascii uppercase or digits.&lt;/li&gt;
&lt;li&gt;$c_{15}, \dots, c_{19}$ is constant&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Unfortunately, this condtion is not enough to find appropriate vector in CVP. So we added customized conditions:&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;$c_0$ to $c_3$ is digits and $c_4$ to $c_{14}$ is ascii uppercase.&lt;/li&gt;
&lt;li&gt;$c_0 &amp;lt; c_1 &amp;lt; c_2 &amp;lt; c_3$.&lt;/li&gt;
&lt;li&gt;$c_{i+1} - c_i \leq 5$ for $4 \leq i \leq 13$.&lt;/li&gt;
&lt;li&gt;$c_4 \in {A,B,C}, c_{14} \in {X,Y,Z}$.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;We test all possible candidates $c_0, c_1, c_2, c_3, c_4, c_{14}$ for each connection.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;The probability that randomly chosen $x$ satisfies this is about &lt;code&gt;1.4%&lt;/code&gt;. And if $x$ satistfies this, $x$ is reveal with a probability about &lt;code&gt;60%&lt;/code&gt;. So We can estimate that we can succeed after about 120 trials. In each connection, the running time is about 2 minutes in my PC. So I ran 10 parallel connections.&lt;/p&gt;
&lt;pre class=&quot;properties&quot;&gt;&lt;code&gt;########
from sage.modules.free_module_integer import IntegerLattice
from sage.all import *
from pwn import *
from Crypto.Util.number import *
from itertools import combinations
from multiprocessing import Pool

from random import randint, choices, seed
from string import ascii_uppercase, digits


q = 0
T = []
U = []
r = None

def conn():
  global r,q,T,U
  r = remote(&quot;190.92.233.181&quot;, 23334)
  r.recvuntil(b&quot; = &quot;)
  q = int(r.recvline())
  r.recvuntil(b&quot; = &quot;)
  T = eval(r.recvline())
  r.recvuntil(b&quot; = &quot;)
  U = eval(r.recvline())

# Directly taken from rbtree's LLL repository
# From https://oddcoder.com/LOL-34c3/, https://hackmd.io/@hakatashi/B1OM7HFVI

#def Babai_CVP(mat, target, M, G):
def Babai_CVP(M, G, target):

  diff = target
  for i in reversed(range(G.nrows())):
    diff -=  M[i] * ((diff * G[i]) / (G[i] * G[i])).round()
  return target - diff


def solve(mat, lb, ub, weight = None):
  num_var  = mat.nrows()
  num_ineq = mat.ncols()

  max_element = 0 
  for i in range(num_var):
    for j in range(num_ineq):
      max_element = max(max_element, abs(mat[i, j]))

  if weight == None:
    weight = num_ineq * max_element

    # sanity checker
  if len(lb) != num_ineq:
    print(&quot;Fail: len(lb) != num_ineq&quot;)
    return

  if len(ub) != num_ineq:
    print(&quot;Fail: len(ub) != num_ineq&quot;)
    return

  for i in range(num_ineq):
    if lb[i] &amp;gt; ub[i]:
      print(&quot;Fail: lb[i] &amp;gt; ub[i] at index&quot;, i)
      return

      # heuristic for number of solutions
  DET = 0

  if num_var == num_ineq:
    DET = abs(mat.det())
    num_sol = 1
    for i in range(num_ineq):
      num_sol *= (ub[i] - lb[i])
    if DET == 0:
      print(&quot;Zero Determinant&quot;)
    else:
      num_sol //= DET
      # + 1 added in for the sake of not making it zero...
      print(&quot;Expected Number of Solutions : &quot;, num_sol + 1)

  # scaling process begins
  # max_diff = max([ub[i] - lb[i] for i in range(num_ineq)])
  # applied_weights = []

  # for i in range(num_ineq):
  #   ineq_weight = weight if lb[i] == ub[i] else max_diff // (ub[i] - lb[i])

  #   # customized
  #   # if i &amp;lt; 12: ineq_weight *= 1


  #   applied_weights.append(ineq_weight)
  #   for j in range(num_var):
  #     mat[j, i] *= ineq_weight
  #   lb[i] *= ineq_weight
  #   ub[i] *= ineq_weight

  # Solve CVP
  target = vector([(lb[i] + ub[i]) // 2 for i in range(num_ineq)])
  result = Babai_CVP(M, G, target)

  for i in range(num_ineq):
    if (lb[i] &amp;lt;= result[i] &amp;lt;= ub[i]) == False:
      #print(&quot;Fail : inequality does not hold after solving&quot;)
      return result, -1
  fin = None

  if DET != 0:
    mat = mat.transpose()
    fin = mat.solve_right(result)

  ## recover your result
  return result, fin


varnum = 9 + 90 # c5 to c13, a0 to a89 (we fix c0,c1,c2c3,c4,c14)
eqnum = 10 + 90 # 10 : c condition, 90 : given equation
B = bytes_to_long(b'_cfrt')
mat = matrix(ZZ, varnum, eqnum)
M = None
G = None

def init_mat():
  FACTOR = (q//4) // 5
  #print(FACTOR)
  #print(U[0])
  global mat, M, G
  mat = matrix(ZZ, varnum, eqnum)
  M = None
  G = None

  #varnum = 9 + 90 # c5 to c13, a0 to a89 (we fix c0,c1,c2c3,c4,c14)
  #eqnum = 10 + 90 # 10 : c condition, 90 : given equation
  mat[0, 0] = 1 * FACTOR

  for i in range(8):
    mat[i, i+1] = -1* FACTOR
    mat[i+1, i+1] = 1* FACTOR

  mat[8, 9] = 1* FACTOR

  # given equation
  for i in range(90):
    for j in range(9):
      mat[j, i + 10] = T[i] * 256^(14 - j)
    mat[i+9, i + 10] = -q

  M = IntegerLattice(mat, lll_reduce=True).reduced_basis
  G = M.gram_schmidt()[0]
  print(&quot;init_mat done&quot;)

def LLL(c0, c1, c2, c3, c4, c14):
  FACTOR = (q//4) // 5
  #print(&quot;now&quot;, c0,c1,c2,c3)
  varnum = 9 + 90 # c5 to c13, a0 to a89 (we fix c0,c1,c2c3,c4,c14)
  eqnum = 10 + 90 # 10 : c condition, 90 : given equation
  lb = [0]*eqnum
  ub = [0]*eqnum

  # c condition
  lb[0] = 65* FACTOR
  ub[0] = 70* FACTOR

  for i in range(8):
    lb[i+1] = 0* FACTOR
    ub[i+1] = 5* FACTOR

  lb[9] = 85* FACTOR
  ub[9] = 90* FACTOR

  # given equation
  for i in range(90):
    lb[i+10] = U[i]+1    - T[i] * (B + c0 * 256^19 + c1 * 256^18 + c2 * 256^17 + c3 * 256^16 + c4 * 256^15 + c14 * 256^5) 
    ub[i+10] = U[i]+q//4 - T[i] * (B + c0 * 256^19 + c1 * 256^18 + c2 * 256^17 + c3 * 256^16 + c4 * 256^15 + c14 * 256^5)

  res, fin = solve(M, lb, ub)


  #for i in range(10):
  #  print(res[i] // FACTOR)

  if fin == -1:
    return None


  S = chr(c0) + chr(c1) + chr(c2) + chr(c3) + chr(c4)
  S += chr(res[0] // FACTOR)
  for i in range(1,9):
    gap = res[i] // FACTOR
    S += chr(ord(S[-1]) + gap)
  S += chr(c14)
  S += '_cfrt'
  print(&quot;!!!!!!!!!!!!!!!!!!!!!!!!!&quot;)
  print(S)
  print(&quot;!!!!!!!!!!!!!!!!!!!!!!!!!&quot;)
  vv = bytes_to_long(S.encode())
  r.sendline(str(vv).encode())
  print(r.recvline())
  r.interactive()
  exit(0)
  return S

def gogo():
  conn()
  init_mat()
  COMB_NUM = list(combinations(list(range(48,58)), 4))
  COMB = []
  for a in range(65, 68):
    for b in range(88, 91):
      for elem in COMB_NUM:
        z = list(elem[:])
        z.append(a)
        z.append(b)
        COMB.append(z)

  print(&quot;brute len&quot;, len(COMB))

  #zz = sorted(key)
  #recover = LLL(ord(zz[0]),ord(zz[1]),ord(zz[2]),ord(zz[3]),ord(zz[4]),ord(zz[14]))
  #print(&quot;!!!&quot;, recover)
  #input()
  #exit()


  #r = get_data()
  with Pool(16) as p:
    result = p.starmap(LLL, COMB)

  for vv in result:
    if vv: print(vv)

  r.close()

CNT = 0
while True:
  CNT+=1
  print(&quot;@@@@@@ NOW &quot;, CNT, &quot;@@@@@@&quot;)
  gogo()
#LLL(3,3,6,9)&lt;/code&gt;&lt;/pre&gt;</description>
      <category>CTF/Crypto</category>
      <author>BaaaaaaaaaaaaaaaaaaaaaaarkingDog</author>
      <guid isPermaLink="true">https://baaaaaaaaaaaaaaaaaaaaaaarkingdog.tistory.com/1072</guid>
      <comments>https://baaaaaaaaaaaaaaaaaaaaaaarkingdog.tistory.com/1072#entry1072comment</comments>
      <pubDate>Tue, 13 Dec 2022 15:19:41 +0900</pubDate>
    </item>
    <item>
      <title>[RCTF 2022] magicsign</title>
      <link>https://baaaaaaaaaaaaaaaaaaaaaaarkingdog.tistory.com/1071</link>
      <description>&lt;p&gt;I don&amp;#39;t understand the exact sign &amp;amp; verify logic. However, &lt;code&gt;self.U&lt;/code&gt; has only 9 different elements(4, 11, 18, 24, 26, 78, 81, 133, 135). So it requires the only $O(2^{27})$ bruteforce. To speed-up, rather than run &lt;code&gt;18770&lt;/code&gt; iterations in &lt;code&gt;mix&lt;/code&gt;, run &lt;code&gt;280&lt;/code&gt; iterations and check the validity first.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-cpp&quot;&gt;#include &amp;lt;bits/stdc++.h&amp;gt;
using namespace std;

const int U_SIZE = 18770;

const int Square[8][8] = {{5, 3, 1, 6, 7, 2, 0, 4},
                      {3, 5, 0, 2, 4, 6, 1, 7},
                      {6, 2, 4, 5, 0, 3, 7, 1},
                      {4, 7, 6, 1, 3, 0, 2, 5},
                      {0, 1, 3, 7, 6, 4, 5, 2},
                      {7, 4, 2, 0, 5, 1, 6, 3},
                      {2, 6, 7, 3, 1, 5, 4, 0},
                      {1, 0, 5, 4, 2, 7, 3, 6}};

const int U[U_SIZE] = {...}; // omitted since too long

int U_index_change[U_SIZE];
// 4, 11, 24, 26, 81, 135, 18, 78, 133
// 0, 1,  2,  3,  4,  5    6   7   8
void preprocess(){
  for(int i = 0; i &amp;lt; U_SIZE; i++){
    if(U[i] == 4) U_index_change[i] = 0;
    if(U[i] == 11) U_index_change[i] = 1;
    if(U[i] == 24) U_index_change[i] = 2;
    if(U[i] == 26) U_index_change[i] = 3;
    if(U[i] == 81) U_index_change[i] = 4;
    if(U[i] == 135) U_index_change[i] = 5;
    if(U[i] == 18) U_index_change[i] = 6;
    if(U[i] == 78) U_index_change[i] = 7;
    if(U[i] == 133) U_index_change[i] = 8;    
  }
}

vector&amp;lt;int&amp;gt; mix_extract(vector&amp;lt;int&amp;gt;&amp;amp; T, vector&amp;lt;int&amp;gt;&amp;amp; K, int STEP){
  vector&amp;lt;int&amp;gt; R = T;
  // R = T + K 
  for(int i = 0; i &amp;lt; 9; i++){
    R[i] = Square[T[i]][K[i]];
  }

  for(int i = 1; i &amp;lt;= STEP; i++){
    R[U_index_change[i]] = Square[R[U_index_change[i]]][R[U_index_change[i-1]]];
  }


  for(int i = 0; i &amp;lt; 9; i++){
    R[i] = Square[R[i]][K[i]];
  }
  return R;
}




vector&amp;lt;int&amp;gt; str2vec(string&amp;amp; s){
  vector&amp;lt;int&amp;gt; v;
  for(int i = 0; i &amp;lt; 137; i++){
    v.push_back((int)(s[i] - &amp;#39;0&amp;#39;));
  }
  return v;
}

vector&amp;lt;int&amp;gt; extract_idx(vector&amp;lt;int&amp;gt;&amp;amp; seq){
  vector&amp;lt;int&amp;gt; v;
  v.push_back(seq[4]);
  v.push_back(seq[11]);
  v.push_back(seq[24]);
  v.push_back(seq[26]);
  v.push_back(seq[81]);
  v.push_back(seq[135]);
  v.push_back(seq[18]);
  v.push_back(seq[78]);
  v.push_back(seq[133]);
  return v;
}

string H1 = &amp;quot;00000000073472356175477321551613606604160747333127567726571101035745120413223147437457476323022700377634720722606501264707047017336370411&amp;quot;;

string H2 = &amp;quot;00000000010711433446247704254623443435554621674653377332336216767200574302543717156504476701206620635345005461427376656032425232342514535&amp;quot;;

string S = &amp;quot;02306223007703364406103766161140574436562753732537140704106536206016103512323630130667624207000200703404070320636506361303717760305304121&amp;quot;;

bool total_valid_check(vector&amp;lt;int&amp;gt;&amp;amp; Q_cand){
  auto H1_vec = str2vec(H1);
  auto H1_vec_extract = extract_idx(H1_vec);
  auto S_vec = str2vec(S);
  auto S_vec_extract = extract_idx(S_vec);

  auto S_test = mix_extract(H1_vec_extract, Q_cand, 18769);


  return S_test == S_vec_extract;


}

void solve(){
  auto H1_vec = str2vec(H1);
  auto H1_vec_extract = extract_idx(H1_vec);
  auto S_vec = str2vec(S);
  auto S_vec_extract = extract_idx(S_vec);
  cout &amp;lt;&amp;lt; &amp;quot;S_Vec_extract &amp;quot;;
  for(auto x : S_vec_extract) cout &amp;lt;&amp;lt; x &amp;lt;&amp;lt; &amp;#39; &amp;#39;;
  cout &amp;lt;&amp;lt; &amp;#39;\n&amp;#39;;

  for(int i = 0; i &amp;lt; (1&amp;lt;&amp;lt;27); i++){
    int brute = i;
    vector&amp;lt;int&amp;gt; Q(9);
    for(int j = 0; j &amp;lt; 9; j++){
      Q[j] = brute &amp;amp; 7;
      brute &amp;gt;&amp;gt;= 3;
    }
    auto S_test = mix_extract(H1_vec_extract, Q, 280);
    if(i % 5000000 == 0){
      cout &amp;lt;&amp;lt; i &amp;lt;&amp;lt; &amp;#39;\n&amp;#39;;          
    }

    bool match = true;
    for(int i = 0; i &amp;lt; 6; i++){
      if(S_test[i] != S_vec_extract[i]){
        match = false;
        break;
      }
    }
    if(match &amp;amp;&amp;amp; total_valid_check(Q)){
      cout &amp;lt;&amp;lt; &amp;quot;!! &amp;quot;;
      for(auto x : Q) cout &amp;lt;&amp;lt; x &amp;lt;&amp;lt; &amp;#39; &amp;#39;;
      cout &amp;lt;&amp;lt; &amp;#39;\n&amp;#39;;
    }

    // cout &amp;lt;&amp;lt; &amp;quot;!!! &amp;quot; &amp;lt;&amp;lt; i &amp;lt;&amp;lt; &amp;#39; &amp;#39;;
    // for(auto x : S_test) cout &amp;lt;&amp;lt; x;
    // cout &amp;lt;&amp;lt; &amp;#39;\n&amp;#39;;
  }
}

int main(void){
  preprocess();
  solve();
}&lt;/code&gt;&lt;/pre&gt;</description>
      <category>CTF/Crypto</category>
      <author>BaaaaaaaaaaaaaaaaaaaaaaarkingDog</author>
      <guid isPermaLink="true">https://baaaaaaaaaaaaaaaaaaaaaaarkingdog.tistory.com/1071</guid>
      <comments>https://baaaaaaaaaaaaaaaaaaaaaaarkingdog.tistory.com/1071#entry1071comment</comments>
      <pubDate>Tue, 13 Dec 2022 15:19:15 +0900</pubDate>
    </item>
    <item>
      <title>[RCTF 2022] guess</title>
      <link>https://baaaaaaaaaaaaaaaaaaaaaaarkingdog.tistory.com/1070</link>
      <description>&lt;p&gt;$U[i] // T[i]$ is very similar with $x$. So just calculate $U[i] // T[i]$ and manually check the near integer which has the last 5 chars are &lt;code&gt;_cfrt&lt;/code&gt;.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-python&quot;&gt;from sage.all import *
from pwn import *
from Crypto.Util.number import *

r = remote(&amp;quot;190.92.234.114&amp;quot;, 23334)

r.recvuntil(b&amp;quot; = &amp;quot;)
q = int(r.recvline())

r.recvuntil(b&amp;quot; = &amp;quot;)
T = eval(r.recvline())

r.recvuntil(b&amp;quot; = &amp;quot;)
U = eval(r.recvline())

for i in range(90):
  z = U[i] // T[i]
  print(long_to_bytes(z), z)
  for j in range(-3,3):
    print(long_to_bytes(j+z), j+z)

r.interactive()&lt;/code&gt;&lt;/pre&gt;</description>
      <category>CTF/Crypto</category>
      <author>BaaaaaaaaaaaaaaaaaaaaaaarkingDog</author>
      <guid isPermaLink="true">https://baaaaaaaaaaaaaaaaaaaaaaarkingdog.tistory.com/1070</guid>
      <comments>https://baaaaaaaaaaaaaaaaaaaaaaarkingdog.tistory.com/1070#entry1070comment</comments>
      <pubDate>Tue, 13 Dec 2022 15:18:50 +0900</pubDate>
    </item>
    <item>
      <title>오운완</title>
      <link>https://baaaaaaaaaaaaaaaaaaaaaaarkingdog.tistory.com/1069</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1080&quot; data-origin-height=&quot;1440&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/CnrbB/btrSru97WbF/04anBUkIbDLHzCdMOadl1k/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/CnrbB/btrSru97WbF/04anBUkIbDLHzCdMOadl1k/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/CnrbB/btrSru97WbF/04anBUkIbDLHzCdMOadl1k/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FCnrbB%2FbtrSru97WbF%2F04anBUkIbDLHzCdMOadl1k%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1080&quot; height=&quot;1440&quot; data-origin-width=&quot;1080&quot; data-origin-height=&quot;1440&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;4월부터 크로스핏을 하고 있습니다 벌써 7개월 됐네여 운동 일지는 &lt;a href=&quot;https://blog.encrypted.gg/1051&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;여기&lt;/a&gt;서 확인 가능&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;오늘 드디어 스쿼트랑 데드 100kg 찍었습니다. 운동 조금이라도 해보신 분은 스쿼트 데드 100kg가 7개월씩이나 걸릴일인가 갸우뚱할수도 있지만 몸무게가 58kg여서ㅎㅎㅎ,,, 개인적으로 살 불리는게 굉장히 힘듭니다. 운동 시작할 당시에는 56kg였다가 조금 찌긴 했는데 58kg-60kg에서 체중이 계속 진동합니다. 물론 아무거나 막 집어먹으면 살이 붙긴 하겠지만 그런걸 원하는건 아니고 클린 푸드 위주로 먹으려고 노력하는데 쉽지가 않네요. 계속 더 열심히 먹어야겠습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;현재 중량은 스쿼트 100kg, 데드 100kg, 벤치프레스 52kg, 오버헤드프레스 45kg입니다. 3대 250이네여&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1171&quot; data-origin-height=&quot;554&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/7PytZ/btrSq87n43t/OymgtQvYO5KJ2mcnaPChN0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/7PytZ/btrSq87n43t/OymgtQvYO5KJ2mcnaPChN0/img.png&quot; data-alt=&quot;http://www.liftcalculator.com/&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/7PytZ/btrSq87n43t/OymgtQvYO5KJ2mcnaPChN0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F7PytZ%2FbtrSq87n43t%2FOymgtQvYO5KJ2mcnaPChN0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1171&quot; height=&quot;554&quot; data-origin-width=&quot;1171&quot; data-origin-height=&quot;554&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;http://www.liftcalculator.com/&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;스쿼트와 오버헤드프레스에 비해 상대적으로 데드리프트와 특히 벤치프레스가 약합니다. 사실 데드가 스쿼트보다 높은 경우가 많은데 저는 오히려 스쿼트가 먼저 100kg에 도달했네요. 데드의 경우는 1rm을 넘으면 다리로 밀어서 땅에서 뽑히긴 하는데 정강이 구간을 통과할랑말랑할때 등이 못받쳐주고 내려놓게 되기 때문에 가슴과 등 운동을 앞으로 많이 해야할 것 같습니다. 그나마 가벼워서 풀업은 잘 땡겨져서 벤치 계속 하면서 풀업도 틈틈히 하면 될듯...??&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;올해 가장 잘한 선택 중 하나가 운동을 시작한거라고 생각하고 있습니다. 근육이 붙고 체지방은 빠졌고 아직 몸이 엄청 이뻐진건 아니지만 2n년간 숨어있던 복근도 (가만히 있을땐 안보이지만 누워서 크런치 자세 느낌으로 힘을 주면) 관찰이 됩니다. 계속 열심히 해서 내년 3월쯤에는 3대 300에 도달하면 좋겠네요. 그러려면 운동도 운동인데 살이 좀 붙어야합니다. 일단 60kg는 빨리 넘기는걸로,,, 아직 갈 길이 한참 멀지만 머슬업이랑 핸드스탠드푸쉬업이랑 핸드스탠드워크도 성공하고 싶습니다. ㅎㅇㅌ!&lt;/p&gt;</description>
      <category>일상/의식의 흐름</category>
      <author>BaaaaaaaaaaaaaaaaaaaaaaarkingDog</author>
      <guid isPermaLink="true">https://baaaaaaaaaaaaaaaaaaaaaaarkingdog.tistory.com/1069</guid>
      <comments>https://baaaaaaaaaaaaaaaaaaaaaaarkingdog.tistory.com/1069#entry1069comment</comments>
      <pubDate>Wed, 30 Nov 2022 14:57:13 +0900</pubDate>
    </item>
    <item>
      <title>[SECCON CTF 2022] janken vs kurenaif</title>
      <link>https://baaaaaaaaaaaaaaaaaaaaaaarkingdog.tistory.com/1068</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;prob.py&lt;/b&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1668326330059&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;import os
import signal
import random
import secrets

FLAG = os.getenv(&quot;FLAG&quot;, &quot;fake{cast a special spell}&quot;)


def janken(a, b):
    return (a - b + 3) % 3


signal.alarm(1000)
print(&quot;kurenaif: Hi, I'm a crypto witch. Let's a spell battle with me.&quot;)

witch_spell = secrets.token_hex(16)
witch_rand = random.Random()
witch_rand.seed(int(witch_spell, 16))
print(f&quot;kurenaif: My spell is {witch_spell}. What about your spell?&quot;)

your_spell = input(&quot;your spell: &quot;)
your_random = random.Random()
your_random.seed(int(your_spell, 16))

for _ in range(666):
    witch_hand = witch_rand.randint(0, 2)
    your_hand = your_random.randint(0, 2)

    if janken(your_hand, witch_hand) != 1:
        print(&quot;kurenaif: Could you come here the day before yesterday?&quot;)
        quit()

print(&quot;kurenaif: Amazing! Your spell is very powerful!!&quot;)
print(f&quot;kurenaif: OK. The flag is here. {FLAG}&quot;)&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;It is well-known that python random module is not cryptophically secure. All we need is to find a integer seed which generates 666 target values. When&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;I first tried to analyze the exact logic for the random module in python but it is too boring. Luckily I find &lt;a href=&quot;https://github.com/deut-erium/RNGeesus&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;this repository&lt;/a&gt; and it contains almost everything I want.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Since the whole code is too long, I will introduce a handmade method in Breaker class.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;mersenne.py (partial)&lt;/b&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1668326672937&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;class BreakerPy(Breaker):
    # ...
    def state_recovery_rand_partial(self, outputs):
        &quot;&quot;&quot;
        state recovery for given prob
        &quot;&quot;&quot;
        MT = [BitVec(f'MT[{i}]',32) for i in range(624)]
        values = []
        start_time = time()
        S = Solver()
        for i in range(len(outputs)):
            if i%624==0:
                self.twist_state(MT)
            S.add(LShR(self.tamper_state(MT[i%624]),30)==outputs[i])
        if S.check()==sat:
            print(&quot;time taken :&quot;,time()-start_time)
            model = S.model()
            mt = {str(i): model[i].as_long() for i in model.decls()}
            mt = [mt[f'MT[{i}]'] for i in range(len(model))]
            return mt
    # ...&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;I find a candidate mersenne state using state_recovery_rand_partial method then find a corresponding seed.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;solver.py&lt;/b&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1668326781329&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;from pwn import *
from mersenne import *
import random

def conv(a):
    return (a+1)%3

r = remote(&quot;janken-vs-kurenaif.seccon.games&quot;, 8080)

r.recvuntil(&quot;spell is &quot;)
spell = r.recvuntil(&quot;.&quot;)[:-1]

print(spell)

witch_rand = random.Random()
witch_rand.seed(int(spell, 16))

outputs = [conv(witch_rand.randint(0, 2)) for _ in range(666)]


b = BreakerPy()
mt = b.state_recovery_rand_partial(outputs)

print(&quot;mt recovered&quot;)

R = random.Random()
R.setstate((3, tuple(mt) + (624,), None))

for i in range(666):
    assert(R.randint(0,2) == outputs[i])

print(&quot;assert passed&quot;)

R = random.Random()
#R.seed((1))
R.setstate((3, tuple(mt) + (624,), None))

output32 = [R.getrandbits(32) for _ in range(624)]
seeds = b.get_seeds_python(output32, 624)


if not seeds:
    exit()

print(&quot;!!! seeds!!!!&quot;, seeds)

seed_int = 0

for i in range(len(seeds)):
    seed_int |= (seeds[i] &amp;lt;&amp;lt; (32*i))

r.sendline(hex(seed_int))

r.interactive()&lt;/code&gt;&lt;/pre&gt;</description>
      <category>CTF/Crypto</category>
      <author>BaaaaaaaaaaaaaaaaaaaaaaarkingDog</author>
      <guid isPermaLink="true">https://baaaaaaaaaaaaaaaaaaaaaaarkingdog.tistory.com/1068</guid>
      <comments>https://baaaaaaaaaaaaaaaaaaaaaaarkingdog.tistory.com/1068#entry1068comment</comments>
      <pubDate>Sun, 13 Nov 2022 17:06:31 +0900</pubDate>
    </item>
    <item>
      <title>[SECCON CTF 2022] this_is_not_lsb</title>
      <link>https://baaaaaaaaaaaaaaaaaaaaaaarkingdog.tistory.com/1067</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;prob.py&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1668325796474&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;from Crypto.Util.number import *
from flag import flag

p = getStrongPrime(512)
q = getStrongPrime(512)
e = 65537
n = p * q
phi = (p - 1) * (q - 1)

d = pow(e, -1, phi)

print(f&quot;n = {n}&quot;)
print(f&quot;e = {e}&quot;)
print(f&quot;flag_length = {flag.bit_length()}&quot;)

# Oops! encrypt without padding!
c = pow(flag, e, n)
print(f&quot;c = {c}&quot;)

# padding format: 0b0011111111........
def check_padding(c):
    padding_pos = n.bit_length() - 2
    m = pow(c, d, n)

    return (m &amp;gt;&amp;gt; (padding_pos - 8)) == 0xFF


while True:
    c = int(input(&quot;c = &quot;))
    print(check_padding(c))&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;In textbook RSA, when ciphertext $E(P) = P^e$ is given, ciphertext for $E(P' = mP) = P^e \cdot m^e$&amp;nbsp; can be easily calculated without knowing $P$.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;When we send $c \cdot M^e$, we can check whether $2^{1022} - 2^{1024} \leq flag \cdot M \leq 2^{1022} -1$ or not.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Once we find appropriate $M$ satisfies 2^{1022} - 2^{1024} \leq flag \cdot a$, then set $a$ as lower bound and possible to recover maximum $M$ such that $flag \cdot M \leq 2^{1022} -1$ using binary search.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;solver.py&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1668326175737&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;from pwn import *
from Crypto.Util.number import *
r = remote(&quot;this-is-not-lsb.seccon.games&quot;, 8080)


r.recvuntil(&quot; = &quot;)
n = int(r.recvline())
r.recvuntil(&quot; = &quot;)
e = int(r.recvline())
r.recvuntil(&quot; = &quot;)
flag_len = int(r.recvline())
r.recvuntil(&quot; = &quot;)
c = int(r.recvline())


def query(factor):
  r.recvuntil(&quot; = &quot;)
  val = c * pow(factor, e, n) % n
  r.sendline(str(val).encode())
  z = r.recvline()
  return z == b'True\n'

st = 2**438
en = 2**439 - 1

factor = 2**576 * 196

for i in range(584,-1,-1):
  adder = 2**i
  while query(factor + adder):
    factor += adder
    print(&quot;!! add&quot;,i)


#factor = 48663794436922351897392835332645276106957960444910813902095379757782525882180340752407585793044725993977469588294850480616647015758190038588490706033703755590689470468363797990
  
flag = (2**1022 - 1)//factor


print(long_to_bytes(flag))&lt;/code&gt;&lt;/pre&gt;</description>
      <category>CTF/Crypto</category>
      <author>BaaaaaaaaaaaaaaaaaaaaaaarkingDog</author>
      <guid isPermaLink="true">https://baaaaaaaaaaaaaaaaaaaaaaarkingdog.tistory.com/1067</guid>
      <comments>https://baaaaaaaaaaaaaaaaaaaaaaarkingdog.tistory.com/1067#entry1067comment</comments>
      <pubDate>Sun, 13 Nov 2022 16:56:18 +0900</pubDate>
    </item>
    <item>
      <title>[실전 알고리즘] 0x1F강 - 트라이</title>
      <link>https://baaaaaaaaaaaaaaaaaaaaaaarkingdog.tistory.com/1059</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;figure data-ke-type=&quot;video&quot; data-ke-style=&quot;alignCenter&quot; data-video-host=&quot;youtube&quot; data-video-url=&quot;https://www.youtube.com/watch?v=ZmLe4tc5XRI&quot; data-video-thumbnail=&quot;https://scrap.kakaocdn.net/dn/hFy10/hyPIA3B9MN/zQncXk9W9t83RAAAv4niek/img.jpg?width=480&amp;amp;height=360&amp;amp;face=0_0_480_360&quot; data-video-width=&quot;480&quot; data-video-height=&quot;360&quot; data-video-origin-width=&quot;480&quot; data-video-origin-height=&quot;360&quot; data-ke-mobilestyle=&quot;widthContent&quot;&gt;&lt;iframe src=&quot;https://www.youtube.com/embed/ZmLe4tc5XRI&quot; width=&quot;480&quot; height=&quot;360&quot; frameborder=&quot;&quot; allowfullscreen=&quot;true&quot;&gt;&lt;/iframe&gt;
&lt;figcaption&gt;&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bvEzrc/btrIOR0xwqe/0OZ13ZIV9kcWZhENKhG5BK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bvEzrc/btrIOR0xwqe/0OZ13ZIV9kcWZhENKhG5BK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bvEzrc/btrIOR0xwqe/0OZ13ZIV9kcWZhENKhG5BK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbvEzrc%2FbtrIOR0xwqe%2F0OZ13ZIV9kcWZhENKhG5BK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1920&quot; height=&quot;1080&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;안녕하세요, 드디어 마지막 강이라니 가슴이 웅장해집니다. 마지막인만큼 난이도도 끝판왕일 수 있지만 개인적으로는 꽤 좋아하는 알고리즘 중 하나여서 같이 즐거운 마음으로 배워봅시다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/b0cqVZ/btrIPX0Rmey/70nCflmNh0kpIqDurKAGb1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/b0cqVZ/btrIPX0Rmey/70nCflmNh0kpIqDurKAGb1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/b0cqVZ/btrIPX0Rmey/70nCflmNh0kpIqDurKAGb1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fb0cqVZ%2FbtrIPX0Rmey%2F70nCflmNh0kpIqDurKAGb1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1920&quot; height=&quot;1080&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;아쉽게도 트라이는 STL로 날먹을 할 수가 없습니다. 트라이로 풀어야 하는 문제가 나오면 직접 정직하게 짜셔야 합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bLRlAg/btrIZ5qYUuJ/sWyzhKDdG5FIikQ2oeMGZ0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bLRlAg/btrIZ5qYUuJ/sWyzhKDdG5FIikQ2oeMGZ0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bLRlAg/btrIZ5qYUuJ/sWyzhKDdG5FIikQ2oeMGZ0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbLRlAg%2FbtrIZ5qYUuJ%2FsWyzhKDdG5FIikQ2oeMGZ0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1920&quot; height=&quot;1080&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;트라이는 문자열을 효율적으로 처리하기 위한 트리 자료구조입니다. 트라이 자료구조에서 단어들을 저장한 예시가 저기 그림에 있는데 아마 벌써부터 뭔가 심상치않고 구현이 상당히 어려울 것 같은 느낌이 듭니다. 그런데 사실 대충 느낌적으로 자료구조의 동작 원리를 이해할 수는 있을 것 같습니다. 트리의 루트에서 시작해서 초록색 원이 있는 곳까지 읽어나가면 각 단어에 대응이 됩니다. 예를 들어 가장 왼쪽의 E를 보면, 루트에서 E에 도달할 때 까지 A, P, P, L, E 순으로 방문을 하기 때문에 단어 APPLE에 대응이 됩니다. 일단 이 정도로만 느낌을 잡고 넘어갑시다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/b5Q8ZL/btrLy2ZgmI7/o8u4Y26XjPeAcV1GP1hkQK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/b5Q8ZL/btrLy2ZgmI7/o8u4Y26XjPeAcV1GP1hkQK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/b5Q8ZL/btrLy2ZgmI7/o8u4Y26XjPeAcV1GP1hkQK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fb5Q8ZL%2FbtrLy2ZgmI7%2Fo8u4Y26XjPeAcV1GP1hkQK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1920&quot; height=&quot;1080&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;트라이의 성질에 대해 살펴보면 트라이는 이론적인 시간복잡도가 좋습니다. 저기 적힌 |S|는 이전 KMP 단원에서 나왔었지만 S의 길이를 의미합니다. 즉 기존에 단어가 얼마나 많이 저장되어 있는지 여부와 무관하게 무조건 삽입, 탐색, 삭제를 모조리 O(|S|)에 처리할 수 있습니다. 이게 얼마나 좋은건지를 설명하기 위해 삽입, 탐색, 삭제가 효율적이라고 알고있는 다른 자료구조들로 단어들을 처리하는 상황을 생각해보겠습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;만약 단어들을 이진 검색 트리로 처리한다고 하면, 즉 각 단어를 이진 검색 트리의 정점으로 둔다고 하면 단어가 N개 있다고 할 때 이진 검색 트리 단원에서 배웠듯 &lt;span&gt;삽입, 탐색, 삭제 모두&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;O(lg N)번의 비교가 발생하기 때문에 최악의 경우 O(|S| &amp;times; lg N)이 필요하게 됩니다. 만약 해시로 관리를 한다면 &lt;span&gt;삽입, 탐색, 삭제가 모두&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;O(1)인 것 같지만 사실은 해시 값을 계산할 때 O(|S|)이 필요하기도 하고 또 문자열 간의 비교도 발생하기 때문에 삽입, 탐색, 삭제가 O(|S|)입니다. 단, 해시는 이론적으로 O(|S|)지만 실제로는 충돌에 따라 성능이 저하될 수 있는 반면 트라이는 삽입, 탐색, 삭제가 전부 정직하게 O(|S|)에 동작합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이렇게 이론적으로 생각할 때 트라이는 좋은 시간복잡도를 가지고 있지만 한편으로 트라이는 메모리를 아주 많이 차지한다는 단점이 있습니다. 단어들을 그냥 평범하게 배열에 저장하는 것과 비교했을 때 메모리를 무려 '4 &amp;times; 글자의 종류'배 만큼 더 사용하게 됩니다. 예를 들어 각 단어가 알파벳 대문자로만 구성이 되어있다면 글자의 종류가 26개이기 때문에 메모리를 104배나 더 사용합니다. 그래서 지금까지 다룬 자료구조 중에서 최초로 메모리 사용량이 병목이 될 수 있는 자료구조입니다. 그 이유에 대해서는 실제 구현을 다룰 때 설명을 드리도록 하겠습니다. 또 트라이에서 메모리 사용량을 줄일 수 있는 소소한 방법들이 있습니다. 하지만 이 방법을 적용하면 반대로 연산의 속도가 느려지게 됩니다. 일종의 트레이드오프이죠. 이 테크닉이 무엇인지도 구현을 다룰 때 간단하게 짚어드리도록 하겠습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;한편 꼭 알고계셔야 하는 점이 있는데, 이론적으로는 트라이의 시간복잡도가 해시나 이진 검색 트리에 비해 좋은 것과 반대로 구현을 해보면 실제로는 트라이가 훨씬 느리게 동작합니다. 뒤에서 예시로 소개할 문제에서 길이가 최대 500인 10000개의 문자열을 삽입하고 검색하는데 이진 검색 트리와 해시는 각각 76ms, 92ms가 걸린 반면 트라이에서는 무려 472ms가 걸리는 것을 확인할 수 있습니다. 여기에는 다양한 원인이 있는데 그건 트라이를 공부한 후 알아보기로 하고, 기억하고 가시면 좋을건 그냥 일반적인 문자열의 삽입/삭제/검색을 수행해야 하는 상황에서는 트라이보다 해시 혹은 이진 검색 트리를 쓰는 것이 메모리와 시간 측면 모두에서 효율적이고 구현 난이도도 STL을 그대로 가져올 수 있기 때문에 훨씬 낮습니다. 하지만 단순히 문자열의 삽입/삭제/검색만을 수행하는게 아니라 트라이의 성질을 이용해야만 해결이 가능한 문제가 여럿 있기 때문에 트라이를 익혀둘 필요가 있습니다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/10Dvg/btrI8Ryn4nS/0oXkfl3OwmOS4SdRfvYHx1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/10Dvg/btrI8Ryn4nS/0oXkfl3OwmOS4SdRfvYHx1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/10Dvg/btrI8Ryn4nS/0oXkfl3OwmOS4SdRfvYHx1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F10Dvg%2FbtrI8Ryn4nS%2F0oXkfl3OwmOS4SdRfvYHx1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1920&quot; height=&quot;1080&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이제 트라이에서 각 연산들을 수행해보도록 하겠습니다. 바로 삽입부터 확인해봅시다. 우선 처음에는 루트만 있는 트리에서 시작합니다. 여기서 APPLE을 삽입하고 싶습니다. 참고로 트라이에서는 삽입, 탐색, 삭제 이 모든 연산을 할 때 정점을 옮겨다니게 됩니다. 이 때 현재 보고 있는 정점을 주황색 테두리로 표시해두었습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/qCbzu/btrI2Uo7lTW/GwbeXeYlDAWO6Ds8Yb4zKK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/qCbzu/btrI2Uo7lTW/GwbeXeYlDAWO6Ds8Yb4zKK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/qCbzu/btrI2Uo7lTW/GwbeXeYlDAWO6Ds8Yb4zKK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FqCbzu%2FbtrI2Uo7lTW%2FGwbeXeYlDAWO6Ds8Yb4zKK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1920&quot; height=&quot;1080&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;삽입을 할 때에는 A, P, P, L, E 순으로 탐색을 합니다. 이건 검색, 삭제에서도 마찬가지입니다. 현재 보고 있는 정점인 루트에는 값이 A인 자식이 없습니다. 그렇기 때문에 A를 현재 보고 있는 정점의 자식에 추가하고 현재 보고 있는 정점을 루트에서 새로 추가한 A로 옮깁니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/FdWvS/btrI8RZsqT8/jx27VsL7qbvy1juP5gptM0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/FdWvS/btrI8RZsqT8/jx27VsL7qbvy1juP5gptM0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/FdWvS/btrI8RZsqT8/jx27VsL7qbvy1juP5gptM0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FFdWvS%2FbtrI8RZsqT8%2Fjx27VsL7qbvy1juP5gptM0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1920&quot; height=&quot;1080&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;A 다음으로 P를 볼 차례입니다. 현재 보고 있는 정점에는 P라는 자식이 없기 때문에 P를 현재 보고 있는 정점의 자식에 추가하고 현재 보고 있는 정점을 P로 옮깁니다. 뒤의 P, L, E에 대해서도 상황이 동일하기 때문에 P, L, E는 한번에 보여드리도록 하겠습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/Viyo5/btrI2ZxVkNF/LrPttQ551APPvT0wWuoeak/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/Viyo5/btrI2ZxVkNF/LrPttQ551APPvT0wWuoeak/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/Viyo5/btrI2ZxVkNF/LrPttQ551APPvT0wWuoeak/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FViyo5%2FbtrI2ZxVkNF%2FLrPttQ551APPvT0wWuoeak%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1920&quot; height=&quot;1080&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이렇게 E까지 왔습니다. 삽입이 끝난 후에는 마지막 글자에 별도의 표시를 해줍니다. 이 별도의 표시는 초록색 테두리로 나타내겠습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bnpYZa/btrI6se3zLu/w6m0M5itcFeJIm2AnBVId1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bnpYZa/btrI6se3zLu/w6m0M5itcFeJIm2AnBVId1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bnpYZa/btrI6se3zLu/w6m0M5itcFeJIm2AnBVId1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbnpYZa%2FbtrI6se3zLu%2Fw6m0M5itcFeJIm2AnBVId1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1920&quot; height=&quot;1080&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다음으로는 APPLY를 삽입해보겠습니다. 다시 루트에서부터 출발합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/m73iV/btrI3sUayvq/zkWEu9dWd4HT9WvADk6b10/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/m73iV/btrI3sUayvq/zkWEu9dWd4HT9WvADk6b10/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/m73iV/btrI3sUayvq/zkWEu9dWd4HT9WvADk6b10/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fm73iV%2FbtrI3sUayvq%2FzkWEu9dWd4HT9WvADk6b10%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1920&quot; height=&quot;1080&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;현재 보고 있는 정점의 자식 중에 A가 있기 때문에 새 정점을 추가할 필요가 없고 A로 이동하면 됩니다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bvIDPl/btrI2Uo7mOE/JREPNjSlsUKhvUVqAB4aCK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bvIDPl/btrI2Uo7mOE/JREPNjSlsUKhvUVqAB4aCK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bvIDPl/btrI2Uo7mOE/JREPNjSlsUKhvUVqAB4aCK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbvIDPl%2FbtrI2Uo7mOE%2FJREPNjSlsUKhvUVqAB4aCK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1920&quot; height=&quot;1080&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그 뒤의 P, P, L에 대해서도 동일한 상황이기 때문에 L까지는 한번에 이동했습니다. 이전에 다 만들어져있어서 새로운 노드를 만들 필요 없이 L까지 도달할 수 있었습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/lBoJl/btrI2wCHHaM/n00DmzEh9ZkWVzXuTNQIn0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/lBoJl/btrI2wCHHaM/n00DmzEh9ZkWVzXuTNQIn0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/lBoJl/btrI2wCHHaM/n00DmzEh9ZkWVzXuTNQIn0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FlBoJl%2FbtrI2wCHHaM%2Fn00DmzEh9ZkWVzXuTNQIn0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1920&quot; height=&quot;1080&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;하지만 현재 보고 있는 정점의 자식 중에 Y는 없기 때문에 Y의 경우 새로운 정점을 만들어줘야 합니다. 또 문자열의 끝에 도달했기 때문에 별도의 표시를 남깁니다. 이렇게 APPLY의 삽입도 끝났습니다. 나중에 코드로 짜는게 좀 복잡해서 문제인거지 트리를 잘 이해하고 있다면 일단 지금 그림으로 동작 원리를 이해하는데에는 크게 어려움이 없을 것 같습니다. 다음으로는 BANANA를 삽입하겠습니다. 이제부터는 글자를 한 개씩 이동하는 대신에 한번에 바로 보여드리겠습니다. 예상한 결과와 일치하는지 확인해보세요.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/nd2Uj/btrI2Zkmxkn/MGKvklcBk7eiwopdq1IMN0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/nd2Uj/btrI2Zkmxkn/MGKvklcBk7eiwopdq1IMN0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/nd2Uj/btrI2Zkmxkn/MGKvklcBk7eiwopdq1IMN0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fnd2Uj%2FbtrI2Zkmxkn%2FMGKvklcBk7eiwopdq1IMN0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1920&quot; height=&quot;1080&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;BANANA를 삽입하고나면 이렇게 됩니다. 다음으로는 BLACK을 삽입해봅시다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/9DkZI/btrI6qn0gzv/LDm4XY8p4okMx1XVATG7z1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/9DkZI/btrI6qn0gzv/LDm4XY8p4okMx1XVATG7z1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/9DkZI/btrI6qn0gzv/LDm4XY8p4okMx1XVATG7z1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F9DkZI%2FbtrI6qn0gzv%2FLDm4XY8p4okMx1XVATG7z1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1920&quot; height=&quot;1080&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;아마 예상하는 모양 그대로일 것 같습니다. 마지막으로 BAN을 삽입해보는 상황만 확인해보고 Fetch로 넘어가겠습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/l8VSv/btrI3uLbwBP/CVP1Ay6NIAbhVHP6Za3LW1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/l8VSv/btrI3uLbwBP/CVP1Ay6NIAbhVHP6Za3LW1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/l8VSv/btrI3uLbwBP/CVP1Ay6NIAbhVHP6Za3LW1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fl8VSv%2FbtrI3uLbwBP%2FCVP1Ay6NIAbhVHP6Za3LW1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1920&quot; height=&quot;1080&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;BAN을 삽입하면 새로 추가되는 정점이 없고 기존에 있던 정점만을 그대로 타고 가게 됩니다. 트라이에서 단어를 삽입한 후에 초록색으로 나타낸 별도의 표시를 해주는 이유를 여기서 알 수가 있는데, 만약 별도의 표시가 없다면 단어 BAN과 BANANA가 모두 삽입된 상태와 BANANA만 삽입된 상태를 구분할 수가 없습니다. 삽입은 여기까지만 살펴보겠습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cIgA9l/btrIYDoBgcH/ZsjJve0VqALYXS5Y2o0kZk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cIgA9l/btrIYDoBgcH/ZsjJve0VqALYXS5Y2o0kZk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cIgA9l/btrIYDoBgcH/ZsjJve0VqALYXS5Y2o0kZk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcIgA9l%2FbtrIYDoBgcH%2FZsjJve0VqALYXS5Y2o0kZk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1920&quot; height=&quot;1080&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다음으로 특정 문자열이 있는지 검색을 해봅시다. 검색도 삽입과 크게 다를게 없습니다. APPLY를 검색해봅시다. 일단 루트에서 출발합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/ps9H0/btrIZ5rD4CH/0l7upCVqtT7yiczGdR5kD1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/ps9H0/btrIZ5rD4CH/0l7upCVqtT7yiczGdR5kD1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/ps9H0/btrIZ5rD4CH/0l7upCVqtT7yiczGdR5kD1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fps9H0%2FbtrIZ5rD4CH%2F0l7upCVqtT7yiczGdR5kD1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1920&quot; height=&quot;1080&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;먼저 A로 가고&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/KQcqd/btrI6qhgTYo/54dPqdVT7CjGKDvXK0Jyik/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/KQcqd/btrI6qhgTYo/54dPqdVT7CjGKDvXK0Jyik/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/KQcqd/btrI6qhgTYo/54dPqdVT7CjGKDvXK0Jyik/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FKQcqd%2FbtrI6qhgTYo%2F54dPqdVT7CjGKDvXK0Jyik%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1920&quot; height=&quot;1080&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;P로 가고&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/DkkHj/btrI3s0YH3p/X6hgOXVLZZLwfp44zpn7T0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/DkkHj/btrI3s0YH3p/X6hgOXVLZZLwfp44zpn7T0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/DkkHj/btrI3s0YH3p/X6hgOXVLZZLwfp44zpn7T0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FDkkHj%2FbtrI3s0YH3p%2FX6hgOXVLZZLwfp44zpn7T0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1920&quot; height=&quot;1080&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다시 P로 가고&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/t6byq/btrI9nj0rlE/6ExcN7M7SzFOVYMkvLUcrK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/t6byq/btrI9nj0rlE/6ExcN7M7SzFOVYMkvLUcrK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/t6byq/btrI9nj0rlE/6ExcN7M7SzFOVYMkvLUcrK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Ft6byq%2FbtrI9nj0rlE%2F6ExcN7M7SzFOVYMkvLUcrK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1920&quot; height=&quot;1080&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;L로 가고&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/Br0jC/btrI7LZI11q/EWntX2SuE6wvhp4D9XnK81/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/Br0jC/btrI7LZI11q/EWntX2SuE6wvhp4D9XnK81/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/Br0jC/btrI7LZI11q/EWntX2SuE6wvhp4D9XnK81/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FBr0jC%2FbtrI7LZI11q%2FEWntX2SuE6wvhp4D9XnK81%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1920&quot; height=&quot;1080&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;마지막으로 Y로 가면 여기에 단어가 있다는 표시가 있기 때문에 트라이 안에 APPLY가 있음을 알 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/b5O2Vt/btrIZ5d7JUG/L894w1krsHMX03K6AJEvH1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/b5O2Vt/btrIZ5d7JUG/L894w1krsHMX03K6AJEvH1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/b5O2Vt/btrIZ5d7JUG/L894w1krsHMX03K6AJEvH1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fb5O2Vt%2FbtrIZ5d7JUG%2FL894w1krsHMX03K6AJEvH1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1920&quot; height=&quot;1080&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이번에는 트라이에 없는 단어를 찾으려고 해봅시다. BASE를 찾으려고 합니다. 그러면 먼저 루트에서 출발합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/kLOik/btrI3yF9g4c/GaEA5DHkI48xNOsXSK9eg0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/kLOik/btrI3yF9g4c/GaEA5DHkI48xNOsXSK9eg0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/kLOik/btrI3yF9g4c/GaEA5DHkI48xNOsXSK9eg0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FkLOik%2FbtrI3yF9g4c%2FGaEA5DHkI48xNOsXSK9eg0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1920&quot; height=&quot;1080&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;B로 가고&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/tLGjV/btrI9lT1Shh/XZkawnROBkDaUboO9zAvCK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/tLGjV/btrI9lT1Shh/XZkawnROBkDaUboO9zAvCK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/tLGjV/btrI9lT1Shh/XZkawnROBkDaUboO9zAvCK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FtLGjV%2FbtrI9lT1Shh%2FXZkawnROBkDaUboO9zAvCK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1920&quot; height=&quot;1080&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그 다음 A로 간 것 까지는 좋은데&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/Oh08u/btrI1PB339N/kKuKj34fZhR7laxXS9a0Fk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/Oh08u/btrI1PB339N/kKuKj34fZhR7laxXS9a0Fk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/Oh08u/btrI1PB339N/kKuKj34fZhR7laxXS9a0Fk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FOh08u%2FbtrI1PB339N%2FkKuKj34fZhR7laxXS9a0Fk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1920&quot; height=&quot;1080&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;아쉽게도 A 밑에 S는 없습니다. 그래서 트라이 안에 BASE는 없다는걸 알 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bFVBx0/btrI2vRmkD0/5f8ru53G6jxOyl01FmWBkk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bFVBx0/btrI2vRmkD0/5f8ru53G6jxOyl01FmWBkk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bFVBx0/btrI2vRmkD0/5f8ru53G6jxOyl01FmWBkk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbFVBx0%2FbtrI2vRmkD0%2F5f8ru53G6jxOyl01FmWBkk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1920&quot; height=&quot;1080&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;트라이에 없는 단어를 찾는 또 다른 예시를 살펴보겠습니다. 이번에는 APP을 검색해보겠습니다. 따라가는 과정은 생략을 하겠습니다. 마지막 글자인 P까지 잘 도착했지만 이 정점은 단어의 끝이라는 초록색 표시가 된 정점이 아니기 때문에 트라이 안에 APP은 없습니다. 처음에 트라이가 익숙하지 않을 때 지금과 같은 케이스를 실수로 놓치는 경우가 종종 있어서 검색을 할 때 단어의 끝에 도달했는지를 확인해야한다는걸 주의해주세요.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/brUj9L/btrJcFj9ZFr/7VCWPP5E5aSHtBeUXA3VBK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/brUj9L/btrJcFj9ZFr/7VCWPP5E5aSHtBeUXA3VBK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/brUj9L/btrJcFj9ZFr/7VCWPP5E5aSHtBeUXA3VBK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbrUj9L%2FbtrJcFj9ZFr%2F7VCWPP5E5aSHtBeUXA3VBK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1920&quot; height=&quot;1080&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;제거도 별다를게 없습니다. 예를 들어 BAN을 제거한다치면 앞에서 하던대로 해당 위치까지 일단 찾아갑니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/k8i3Q/btrI7Mj2RvS/85a56WwM2FpiSsmf5fpU7K/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/k8i3Q/btrI7Mj2RvS/85a56WwM2FpiSsmf5fpU7K/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/k8i3Q/btrI7Mj2RvS/85a56WwM2FpiSsmf5fpU7K/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fk8i3Q%2FbtrI7Mj2RvS%2F85a56WwM2FpiSsmf5fpU7K%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1920&quot; height=&quot;1080&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그런 다음 그냥 초록색 표시를 없애면 BAN이 제거됩니다. 단 트라이 구조를 망칠 수는 없기 때문에 정점 자체를 제거하면 안됩니다. 그렇기 때문에 트라이는 삭제를 하더라도 이전에 삽입한 정점들은 계속 메모리에 남아있게 되어 일종의 메모리 측면에서 비효율적이고 삭제가 계속 발생하는 환경에서는 트라이가 적합하지 않습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이제 트라이가 무엇인지, 그리고 각 연산이 어떤 식으로 동작하는지는 이해를 다 하셨다고 생각합니다. 그런데 트라이는 구현이 조금 까다롭습니다. 노베이스인 상황에서 밑바닥에서부터 구현을 하기는 좀 많이 힘들다고 생각해서 일단은 저의 구현 코드 설명을 보면서 이해해보고, 나중에 제 코드 참고 없이 insert, find, erase 함수를 직접 짜보는 방식으로 공부를 하는걸 추천드립니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cbguVu/btrJfYyaXeI/BzZL9RQNIT6Op2mqAx3Hok/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cbguVu/btrJfYyaXeI/BzZL9RQNIT6Op2mqAx3Hok/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cbguVu/btrJfYyaXeI/BzZL9RQNIT6Op2mqAx3Hok/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcbguVu%2FbtrJfYyaXeI%2FBzZL9RQNIT6Op2mqAx3Hok%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1920&quot; height=&quot;1080&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;가장 먼저 쓰이는 변수들을 살펴보겠습니다. 저희는 각 정점에 번호를 부여할 예정입니다. 일단 루트의 번호는 1로 고정이고 새로 정점이 추가될 때 마다 2, 3, 4, ... 순으로 번호를 부여합니다. 이렇게 번호를 부여할 때 unused가 쓰이게 됩니다. 0x04강 - 연결 리스트에서 야매 연결 리스트를 구현할 때 unused가 쓰였던 것과 같은 맥락입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;MX는 최대 등장 가능한 글자의 수입니다. 이 값은 문제의 제한 조건으로부터 유추가 가능합니다. 예를 들어 조건 상으로 길이가 최대 500인 문자열이 10000개 들어오는 문제일 경우 10000 * 500으로 둘 수 있고 또 정점의 시작 번호가 0이 아니라 1이기 때문에 대충 +5 정도의 여유를 뒀습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;chk는 이전에 초록색 테두리로 보여드렸던, 해당 정점이 문자열의 끝인지 여부를 저장하는 배열입니다. 마지막으로 nxt는 각 정점에서 자식 정점의 번호를 의미합니다. 지금은 가능한 문자의 종류가 알파벳 소문자로 26개여서 nxt 배열을 nxt[MX][26]으로 선언했는데 만약 문자의 종류가 50개라면 nxt[MX][50]으로 선언을 해야 합니다. 자식 정점의 번호를 이렇게 관리하기 때문에 매 순간마다 이동해야 하는 자식 정점의 번호를 O(1)에 알 수 있지만, 단점으로는 각 정점마다 26칸을 할당하고 있어야 하기 때문에 메모리를 상당히 많이 사용합니다. 앞에서 트라이의 성질을 설명할 때 &lt;span&gt;메모리를 무려 '4&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&amp;times; 글자의 종류'배 만큼 더 사용한다는게 여기서 나오는건데, 배열에 문자열을 그냥 저장하면 각 글자당 그냥 char 1칸이니 1바이트만 사용하는 반면 지금 이 구조에서는 자식 정점의 번호를 저장하기 위해 각 글자마다 int 26칸이 필요하니 무려 &lt;span&gt;4&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&amp;times;&lt;span&gt; 26바이트를 사용합니다. 일단 이 정도로만 이해하고 설명을 이어나가겠습니다. 07, 08번째 줄과 같이 nxt는 -1로 초기화시켜둡니다. 저희는 정점을 돌아다니다가 -1을 만나면 해당 자식 정점이 없다는 사실을 알 수 있습니다.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;10-12번째 줄에 있는 c2i 함수는 글자를 받아 배열의 인덱스로 쓸 수 있게 변환하는 함수입니다. 지금은 대문자만 등장하는 상황을 생각해 'A'는 0, 'B'는 1, ..., 'Z'는 25에 대응시키는 함수인데 만약 대문자도 나오고 소문자도 나온다거나, 대문자와 소문자와 숫자가 모두 나온다거나 하면 이 함수를 상황에 맞게 바꿔 각 문자가 0부터 차례로 대응이 되게끔 해야합니다.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/CACXg/btrJikAdohg/Ulknz68afx1cyNdYIA18kk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/CACXg/btrJikAdohg/Ulknz68afx1cyNdYIA18kk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/CACXg/btrJikAdohg/Ulknz68afx1cyNdYIA18kk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FCACXg%2FbtrJikAdohg%2FUlknz68afx1cyNdYIA18kk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1920&quot; height=&quot;1080&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;실제 트라이 구조를 놓고 설명을 드려보면 이런 식인데, 삽입을 하면서 정점이 새로 생기는 순으로 번호를 부여받습니다. 5번 정점의 자식에는 6번 E, 7번 Y 정점이 있는데 A = 0, B = 1, .. 이렇게 생각을 하면 E는 4이고 Y는 24이니 nxt[5][4] = 6, nxt[5][24] = 7이고 다른 자식 정점은 없어서 나머지 인덱스에 대해서는 nxt[5][...] = -1입니다. &lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;chk 배열은 문자열이 끝인 경우에만 true이니 6, 7, 10, 13, 17에서는 true이고 나머지는 false입니다.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bUsk8x/btrJcFTE3nE/O5wX6nMEcfo6Sy8uZFYmWk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bUsk8x/btrJcFTE3nE/O5wX6nMEcfo6Sy8uZFYmWk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bUsk8x/btrJcFTE3nE/O5wX6nMEcfo6Sy8uZFYmWk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbUsk8x%2FbtrJcFTE3nE%2FO5wX6nMEcfo6Sy8uZFYmWk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1920&quot; height=&quot;1080&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;이제 트라이에서 필요한 각 변수가 무엇을 나타내는지는 충분히 이해가 됐다고 봅니다. 바로 insert 함수부터 확인해봅시다. 앞에서 같이 살펴본 삽입의 과정을 떠올리면서 코드를 보면 이해에 도움이 될 수 있는데, 일단 cur가 앞에서 주황색으로 표시했던 현재 보고 있는 정점입니다. 초기값은 02번째 줄과 같이 ROOT입니다. 그 다음으로 for문을 이용해 글자를 하나씩 따라가며 글자에 대응되는 자식 정점으로 이동합니다. 만약 nxt[cur][c2i(c)]가 -1이라면 자식 정점이 없다는 의미이기 때문에 새로운 정점 번호, 즉 unused를 자식 정점에 줍니다. 그리고 unused++이니 unused는 값이 1 증가합니다. 이후 cur를 nxt[cur][c2i(c)]로 이동시키면 됩니다. 이렇게 이동이 끝난 후에는 chk[cur]를 true로 만들면 됩니다.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;아마 코드를 보기 전에는 정점을 새로 생성하는걸 어떻게 구현해야할지 감이 잘 안왔을 수 있는데 보시는 것과 같이 그다지 어렵지 않게 처리가 가능합니다.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;insert 코드를 잘 이해했으면 find, erase 함수는 insert 함수를 참고해서 구현을 할 수 있을거라고 생각합니다. 시도를 해보셔도 좋고, 아니면 제 코드를 바로 확인하셔도 됩니다.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/uPKv1/btrJlGclTmh/F7CSBPwROkoyEtLVZ99XQk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/uPKv1/btrJlGclTmh/F7CSBPwROkoyEtLVZ99XQk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/uPKv1/btrJlGclTmh/F7CSBPwROkoyEtLVZ99XQk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FuPKv1%2FbtrJlGclTmh%2FF7CSBPwROkoyEtLVZ99XQk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1920&quot; height=&quot;1080&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;find 함수에서도 마찬가지로 자식 정점으로 계속 이동합니다. 단, insert와 다르게 존재하지 않는 자식 정점을 만나면 바로 false를 반환합니다. 마지막 글자에 대응되는 정점에 도달한 후에는 바로 chk[cur]를 반환하면 됩니다.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bWXrJS/btrJgdbWWuw/uK7LF2Q8ASPYfUxHsXyV1k/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bWXrJS/btrJgdbWWuw/uK7LF2Q8ASPYfUxHsXyV1k/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bWXrJS/btrJgdbWWuw/uK7LF2Q8ASPYfUxHsXyV1k/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbWXrJS%2FbtrJgdbWWuw%2FuK7LF2Q8ASPYfUxHsXyV1k%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1920&quot; height=&quot;1080&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;erase 함수 또한 자식 정점으로 계속 이동합니다. 만약 존재하지 않는 자식 정점을 만나면 string s가 트라이에 없다는 의미이니 return을 통해 그대로 함수를 종료하고, 마지막 글자에 대응되는 정점에 도달했다면 chk[cur]를 false로 만듭니다. 만약 반드시 트라이에 존재하는 문자열에 대해서만 erase 함수가 호출된다는 조건이 있을 경우에는 04, 05번째 줄을 생략할 수 있습니다. 코드는 깃헙에 올려두었고 함수 내용을 지운채로 직접 한 번 구현해보는걸 추천드립니다. &lt;a href=&quot;https://github.com/encrypted-def/basic-algo-lecture/blob/master/0x1F/trie_example.cpp&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;(코드)&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;한편 트라이를 이전에 배우셨거나 다른 사람들의 코드를 살펴본 적이 있으시다면 정점을 구조체로 선언하고 자식 정점의 정보를 인덱스로 관리하는 대신 포인터로 관리하는 경우를 흔하게 볼 수 있습니다. 그러면 저는 왜 이런 식으로 구현을 했냐 했을때, 이건 마치 정석적인 연결 리스트 구현 vs 야매 연결 리스트의 관계와 같은 느낌입니다. 여기서 소개드린 제 구현체는 최대 등장 가능한 글자의 수를 미리 계산해 아주 큰 배열을 선언해야 하기 때문에 입력의 범위가 정해진 상황에서만 사용할 수 있는 반면(chk, nxt를 배열 대신 vector와 같은 동적배열로 두면 이 문제를 해결할 수 있지만 관련 설명은 생략하겠습니다) 정점을 동적 할당으로 생성하고 자식 정점을 포인터로 관리하면 더 일반적인 상황에서 적용이 가능합니다. 하지만 알고리즘 문제를 푸는 환경에 한해서는 제 구현체가 더 좋습니다. 64비트 컴퓨터 기준으로 포인터는 8바이트입니다. 그렇기 때문에 자식 정점을 포인터로 관리하면 제 코드와 같이 자식 정점을 int 인덱스로 둘 때에 비해 메모리를 2배 더 사용하게 됩니다. 가뜩이나 트라이가 메모리를 굉장히 많이 사용하는 구조임을 생각해보면 메모리를 2배 더 쓰는건 굉장히 바람직하지 않습니다. 그렇기 때문에 알고리즘 문제를 풀 때 트라이를 쓰는 경우에는 포인터로 자식 정점을 관리하는 대신 제 코드와 같이 큰 배열을 하나 잡고 인덱스로 자식 정점을 관리하는걸 추천드립니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/r1M54/btrJsPmqsdC/8jz3B0IQgPolya1hA9TFuk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/r1M54/btrJsPmqsdC/8jz3B0IQgPolya1hA9TFuk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/r1M54/btrJsPmqsdC/8jz3B0IQgPolya1hA9TFuk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fr1M54%2FbtrJsPmqsdC%2F8jz3B0IQgPolya1hA9TFuk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1920&quot; height=&quot;1080&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;한편 트라이에서 메모리를 줄이는 방법에 대해 간략하게 짚고 넘어가겠습니다. 이 내용은 트라이와 STL에 대한 이해가 충분하지 않으면 좀 많이 어렵게 느껴질 수 있어서 자세하게 안들어가고 아주 피상적으로만 다룰거고, 대회를 노리는 사람 기준으로 알아두면 좋은 내용이긴 하지만 만약 설명을 들었을 때 잘 이해가 가지 않는다면 건너뛰었다가 나중에 다시 확인하셔도 상관은 없습니다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;앞에서 보여드린 코드에서는 각 정점에서 특정 문자에 대응되는 자식 정점을 O(1)에 찾을 수 있도록 하기 위해 자식 정점의 인덱스를 nxt[MX][26] 배열에 저장합니다. 여기서 MX는 앞에서 언급했듯 최대 등장 가능한 글자의 수이고 이 문제에서는 N&amp;middot;|S|으로 계산할 수 있습니다. 그런데 이렇게 되면 필요한 메모리의 양이 너무 커지는 문제가 생깁니다. 가능한 문자의 종류가 26개이면 그나마 나은데 한글 혹은 한자와 같이 문자의 종류가 엄청 많을 경우에는 nxt[MX][10000]과 같은 배열을 잡는게 현실적으로 불가능합니다. 이럴 때에는 자식 정점을 O(1)보다 느리게 찾더라도 메모리를 절약하는 방법을 사용할 수 있습니다. 첫 번째 방법은 각 정점당 26칸을 할당하는 대신 vector와 같은 동적 배열을 사용하는 방법입니다. 예를 들어 자식 정점이 E, Y 2개가 있고 각각 6번과 7번이라면 동적 배열에 ('E', 6), ('Y', 7)을 담는 방법입니다. 이렇게 하면 자식 정점을 찾기 위해 최악의 경우 매 순간마다 26번의 탐색을 해야하기 때문에 시간복잡도는 O(26&amp;middot;|S|)로 늘어나지만 공간복잡도는 O(MX)로 줄어듭니다. 동적 배열 대신 연결 리스트를 사용해도 동일한 상황입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;동적 배열 혹은 연결 리스트 대신 이진 검색 트리나 해시를 사용하는 방법도 있습니다. 자식 정점을 이진 검색 트리나 해시로 관리하면 시간복잡도는 각각 O(lg(26)&amp;middot;|S|) 혹은 O(|S|)가 되고 공간복잡도는 그대로 O(MX)이지만 이진 검색 트리나 해시 자료 구조의 오버헤드가 더 크기 때문에 실제로 사용하는 메모리는 동적 배열이나 연결 리스트에 비해 더 클 것으로 예상할 수 있어요.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;보통 트라이로 푸는 것을 의도하고 낸 문제에서는 고정된 크기의 배열로 잡아도 메모리 초과가 발생하지 않도록 제한을 두는 일이 대부분이긴 하지만 아주 간혹 문자의 종류가 너무 많다던가 하는 이유로 메모리를 계산했을 때 메모리 초과가 발생할 것 같은 상황에서는 여기 나와있는 것과 같이 자식 정점들을 다른 방법으로 저장하는 것을 고려해볼 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bYUEaG/btrLwA3dMRs/lnCpwSQPHgZfkun7UiAI7k/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bYUEaG/btrLwA3dMRs/lnCpwSQPHgZfkun7UiAI7k/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bYUEaG/btrLwA3dMRs/lnCpwSQPHgZfkun7UiAI7k/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbYUEaG%2FbtrLwA3dMRs%2FlnCpwSQPHgZfkun7UiAI7k%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1920&quot; height=&quot;1080&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;자 그런데 저희는 결국 실전적으로 문제를 풀 때 상황이 어떻게 되는지가 궁금합니다. 이론적으로만 보면 자식을 해시로 저장하는게 제일 좋습니다. 시간복잡도와 공간복잡도가 다 최소이기 때문입니다. 그런데 실제로 짜서 돌려보면 그렇지가 않습니다. 제가 실험을 진행한 BOJ 14425 문제는 바로 뒤에서 같이 풀어볼 예정이라 지금 굳이 보고 올 필요는 없습니다. 문제의 상황을 간단하게 설명을 드리면 길이가 500인 단어를 최대 10000번 삽입하고 또 10000번 검색합니다. 이 때 단어는 영어 소문자로만 이루어져 있습니다. 그리고 트라이를 저 5개 각각으로 짜서 돌려보면 시간과 메모리가 저렇게 됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;일단 메모리부터 확인해보면 이론적으로는 고정된 크기의 배열 말고 나머지 4개를 쓰면 공간복잡도에 글자의 종류와 관련된 값이 빠져서 엄청 줄어들어야할 것 같은데 실제로는 그렇지가 않습니다. 강의에서 STL vector나 list 등의 내부 구조까지 다루지는 않았지만 중요한건 오버헤드가 꽤 크다는 사실입니다. 예를 들어 설명을 하면 vector에서는 실제 데이터가 들어가는 곳의 시작과 끝 주소도 저장하고 있다던가, list에서는 각 원소가 이전과 다음 원소의 주소를 들고 있는 등의 이유로 그냥 고정된 크기의 배열에서는 자식 하나당 정직하게 int 1개인 4바이트씩 차지하는 것과 다르게 STL 구조의 특성상 소모되는 별도의 메모리가 있습니다. set와 unordered_set은 구조가 더 복잡하니 말할 필요도 없이 vector, list보다도 훨씬 오버헤드가 큽니다. 그렇기 때문에 동적 배열과 연결 리스트 방식에서는 메모리가 줄긴 하지만 이론적인 수치처럼 26배씩 감소하는건 아니고 한 2배 정도만 감소합니다. 또 이진 검색 트리는 그냥 고정된 배열을 쓰는 것과 거의 비슷한 메모리 사용량을 보여주고 해시는 오히려 메모리 사용량이 훨씬 더 큽니다. 물론 문자의 종류가 26개가 아니라 60개 이런식으로 더 많았다면 감소되는 정도가 더 컸을 수 있지만 아무튼 생각만큼 메모리의 감소가 많이 일어나지는 않는다는 점을 확인 가능합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다음으로 시간을 살펴보면 고정된 크기의 배열을 이용하는게 제일 빠르고 동적 배열과 연결 리스트로 냈을 땐 더 느립니다. 동적 배열과 연결 리스트에서 시간이 더 오래 걸리는 이유는 자식을 O(1)에 찾는게 아닌 O(26)에 찾기 때문인데, 사실 최악의 경우에 26번 탐색을 해야하는건 맞지만 그렇다고 정말 매번 26번 탐색을 하는건 아닐테니 26배까지는 아니고 4-8배 정도 느린 것을 확인 가능합니다. 참고로 맨 처음 강의 자료를 만들면서 동적 배열과 연결 리스트 각각으로 구현을 해서 내봤더니 실행 시간이 별 차이가 없길래&amp;nbsp; 직접 자식을 탐색하는데 오래 걸릴 데이터를 만들어서 추가했습니다. 문제의 요청 게시판을 보시면 제가 데이터 추가 요청을 했던걸 확인할 수 있습니다. 다음으로 이진 검색 트리는 어느 정도 빠르긴 하지만 당연히 고정된 크기의 배열을 이용하는 것 보다는 느리고, 해시는 영 못써먹을 물건이 됐습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;정리하면 트라이 문제를 만났을 때에는 자식을 그냥 고정된 크기의 배열로 푸는게 제일 낫습니다. 그런데 출제자가 메모리 제한을 너무 낮게 세팅해서 사용되는 메모리의 양을 따져보니 고정된 크기의 배열을 이용할 경우 무조건 메모리 초과가 발생한다면 정말 어쩔 수 없이 자식을 동적 배열, 즉 vector를 써서 관리하는 방식으로 선회를 할 수 있습니다. 그 외에 연결 리스트/이진 검색 트리/해시를 쓰는 방법은 딱히 실전에서 활용 가치가 없습니다. 당장 저도 트라이가 정해인 문제를 만나면 여기 써놓은 것과 같이 일단은 고정된 크기의 배열로 풀었을 때의 메모리 사용량을 가늠해보고 메모리 제한 안에 들어오면 고정된 크기의 배열을 쓰고, 제한 안에 들어오지 못하면 vector를 써서 풉니다. 사실 정해가 트라이인 문제라면 메모리 제한을 넉넉하게 두는게 맞지만, 출제자가 악랄하거나 혹은 의도한 풀이는 다른 알고리즘이고 트라이 풀이를 인지하지 못했다면 가끔 메모리에서 문제가 생기는 일이 발생할 수 있어서 동적 배열을 쓰는 방식 정도는 익혀두면 절체절명의 순간에서 큰 도움이 될 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;실전에서 쓸 일이 없는 것과는 별개로 자식을 동적 배열, 연결 리스트, 이진 검색 트리, 해시로 관리하는 코드를 작성해보는건 좋은 연습이 될 것 같아서 한 번 직접 짜보시는걸 추천드립니다. 제 코드를 굳이 소개할 생각은 없지만 제가 어떻게 짰는지 궁금하시면 BOJ 14425번 문제에 제가 제출한 코드들을 열어보세요.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bSkunR/btrJACoMp0F/EI1ITAkdIq8lonsyo8XHp0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bSkunR/btrJACoMp0F/EI1ITAkdIq8lonsyo8XHp0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bSkunR/btrJACoMp0F/EI1ITAkdIq8lonsyo8XHp0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbSkunR%2FbtrJACoMp0F%2FEI1ITAkdIq8lonsyo8XHp0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1920&quot; height=&quot;1080&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;어쩌다보니 연습 문제 챕터가 나오기 전에 먼저 문제를 소개했는데 아무튼 &lt;a href=&quot;https://www.acmicpc.net/problem/14425&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;BOJ 14425번: 문자열 집합&lt;/a&gt; 문제를 트라이로 풀어봅시다. 물론 앞에서 본 코드를 그대로 가져오면 되긴 하지만 직접 풀어보는걸 추천드립니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cn3fBz/btrJBlT4cRa/CdLKGpwIRKQdP9LSMpcgAK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cn3fBz/btrJBlT4cRa/CdLKGpwIRKQdP9LSMpcgAK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cn3fBz/btrJBlT4cRa/CdLKGpwIRKQdP9LSMpcgAK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fcn3fBz%2FbtrJBlT4cRa%2FCdLKGpwIRKQdP9LSMpcgAK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1920&quot; height=&quot;1080&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;저는 당연히 제 코드를 그대로 가져왔습니다. 앞쪽은 다 똑같습니다. 제거 연산은 등장하지 않기 때문에 코드 길이도 줄일겸 뺐습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/8fJPt/btrJAp4hzvP/pTDexvndnPD7nEn94oELIK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/8fJPt/btrJAp4hzvP/pTDexvndnPD7nEn94oELIK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/8fJPt/btrJAp4hzvP/pTDexvndnPD7nEn94oELIK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F8fJPt%2FbtrJAp4hzvP%2FpTDexvndnPD7nEn94oELIK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1920&quot; height=&quot;1080&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그리고 main에서는 그냥 n번에 걸쳐 insert하고, 또 m번에 걸쳐 find를 하면 끝입니다. 정말 트라이의 기초적인 예제같은 문제라 코드에서 설명할게 많지는 않습니다. &lt;a href=&quot;https://github.com/encrypted-def/basic-algo-lecture/blob/master/0x1F/14425.cpp&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;(코드)&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;단 한 가지 생각해보면 좋을 점이 있는데, 지금은 삽입되는 문자열에 중복이 없다는 단서가 있습니다. 그런데 삽입되는 문자열에 중복이 있을 수 있다면 어떻게 될까요? 예를 들어 같은 문자열을 여러 번 삽입할 수 있고 find에서는 문자열 s가 들어있는 개수를 반환해야 하는 등 중복을 관리해줘야 하는 상황이 있을 수 있습니다. 이건 chk 배열을 약간만 잘 바꾸면 해결을 할 수 있고, 제가 답을 드리는 대신 여러분에게 생각해볼 거리로 남겨두겠습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그런데 이 문제가 트라이 단원에 있으니 트라이로 해결을 했지, 만약 해시나 이진 검색 트리 단원에 이 문제를 뒀다면 굉장히 자연스럽게 이 둘을 이용해서 문제를 풀어냈을 것입니다. 그냥 해시 혹은 이진 검색 트리에 문자열을 다 넣어두고 검색을 하면 됩니다. 이 문제를 트라이, 해시, 이진 검색 트리 각각으로 풀었을 때 시간과 메모리를 확인해봅시다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/KD3pQ/btrQUBuYcUK/WxNTgXSk6R05A6dS7HCnl1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/KD3pQ/btrQUBuYcUK/WxNTgXSk6R05A6dS7HCnl1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/KD3pQ/btrQUBuYcUK/WxNTgXSk6R05A6dS7HCnl1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FKD3pQ%2FbtrQUBuYcUK%2FWxNTgXSk6R05A6dS7HCnl1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1920&quot; height=&quot;1080&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;일단 이론적인 시간복잡도와 공간복잡도는 한 번 잘 이해해보시길 바라고, 실제 시간과 메모리를 보면 차이가 정말 어마어마합니다. 일단 시간도 트라이가 5-6배 가까이 느리고, 메모리는 무려 65배 가까이 더 많이사용합니다. 이진 검색 트리와 해시에서 메모리 사용량이 78MB, 79MB가 아니라 7.8MB, 7.9MB입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;먼저 시간이 왜 이렇게 차이나는지를 보면 기본적으로 메모리의 접근은 단순 연산보다 속도가 느립니다. 그런데 트라이에서는 정점을 정직하게 |S|칸 이동하고 심지어 이게 굉장히 큰 배열에서 이루어져서 cache hit rate가 굉장히 나쁩니다. 반면 이진 검색 트리나 해시에서는 트라이와 달리 정점의 이동이 그렇게 많지 않고, 두 문자열간의 비교를 이진 검색 트리 기준 O(lgN)번, 해시 기준 O(1)번 하긴 하지만 사실 문자열의 특성상 비교를 하다가 불일치가 발생하면 바로 비교를 종료하기 때문에 이론적으로 각 삽입/탐색 당 O(lgN&amp;middot;|S|) 혹은 O(|S|)인 것과 별개로 실제로는 더 빠르게 동작합니다. 그렇기 때문에 빅오표기법으로 나타내는 시간복잡도와 달리 실제로는 트라이보다 이진 검색 트리나 해시가 더 시간이 적게 걸립니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다음으로 메모리를 보면, 트라이가 메모리를 많이 쓰는거야 계속 언급했던거지만 이진 검색 트리나 해시에서는 각 글자가 1바이트 char인 반면 트라이에서는 자식 정보를 저장할 때 4바이트 int를 사용하기 때문에 이 문제처럼 글자의 종류가 26개일 때 무려 4 &amp;times; 26 = 104배의 메모리를 더 씁니다. 다만 실제로는 65배 정도 차이가 났고 이 정도의 차이는 이진 검색 트리나 해시에 약간의 오버헤드가 있음을 감안해서 이해할 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;지금 이렇게 트라이에서 시간과 메모리가 느린 이유에 대해 설명한 부분이 잘 이해가 안가면 이유는 생각하지 말고 결론만 이해하셔도 됩니다. 트라이가 문자열의 삽입/탐색/삭제 등을 처리할 수 있는건 맞지만 정말 정직하게 문자열의 삽입/탐색/삭제만 있는 상황에서는 트라이 대신 이진 검색 트리나 해시를 쓰는게 낫습니다. 트라이는 구조의 특성상 메모리를 많이 차지하고 또 속도도 이론적인 시간복잡도와 별개로 좋지 않은 편입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그런데 그렇다면 이렇게 속도도 구리고 메모리도 구린 트라이는 어떨 때 활용이 될 수 있는걸까요? 대표적인 활용 사례 중 하나가 자동 완성 기능입니다. 우리가 검색 엔진에서 키워드를 일부만 입력해도 그 값을 접두사로 가지는 여러 키워드의 목록을 실시간으로 확인할 수 있습니다. 가장 쉽게 떠올릴 수 있는 방법은 그냥 매번 사용자가 현재까지 입력한 키워드를 가지고 서버가 가지고 있는 키워드의 목록과 비교하는 방법이지만 이렇게 되면 속도가 상당히 느립니다. 이 기능을 효율적으로 구현해야 한다고 치면 미리 서버가 가지고 있는 키워드를 가지고 트라이를 만들어두고, 사용자가 무언가를 입력할 때 마다 트라이에서 정점을 타고 들어가면 더 효율적으로 구현할 수 있습니다. 실생활에서의 예시는 이렇고 알고리즘 문제에서의 쓰임새를 생각해보면 문제가 문자열과 관련이 있는데 특히 접두사나 접미사와 관련된 무언가를 요구할 경우 트라이가 쓰이지는 않을까 의심해볼 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/ICkaM/btrJCqf4TNi/GnEnhaJqYKhLCkbzcbWwpK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/ICkaM/btrJCqf4TNi/GnEnhaJqYKhLCkbzcbWwpK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/ICkaM/btrJCqf4TNi/GnEnhaJqYKhLCkbzcbWwpK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FICkaM%2FbtrJCqf4TNi%2FGnEnhaJqYKhLCkbzcbWwpK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1920&quot; height=&quot;1080&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이번 강의에서 다룰 내용은 이게 전부입니다. 단순히 문자열을 삽입하고 찾는 상황에서는 앞에서 설명했듯 트라이가 그다지 유용하지 않기 때문에 오늘 내용이 이해할만했다면 실제로 알고리즘 문제에서 써먹을 수 있게 응용 문제까지 제대로 확인을 해보시는걸 추천드립니다. 만약 내용이 다소 어렵게 느껴졌다면 어차피 트라이 문제를 마주하더라도 풀어내기 힘들테니 그냥 코드는 제껴두고 개념만 이해하고 넘어가셔도 상관은 없습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이렇게 바킹독의 실전 알고리즘 강의가 끝이 났습니다. 대학교 3학년 시절 처음 블로그에 강의를 올리며 혼자 뚝딱뚝딱 만들던걸 블로그 기준으로는 3년 8개월, 유튜브 기준으로는 2년 6개월이나 걸려서 마무리지을 수 있었네요. 그 사이 저는 대학도 졸업하고 석사도 졸업해서 척척석사가 되었습니다. 20대의 대충 1/3을 갈아넣은 결과물이라고 생각하니 참 말도 안되게 오래걸렸다 싶긴 하지만 제 본업이 있는 와중에도 틈틈히 열심히 만들었다는걸 이해해주시면 감사하겠습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;강의를 아껴주시고 또 만드는 동안 응원해주신 분들께 감사드립니다. 만약 이게 오프라인 강의였다면 쫑파티하면서 다같이 피자도 조지고 맥주도 조지고 했을텐데 온라인이라 아쉽네요. 아쉬운대로 제 메일로 피자 기프티콘 쏴주시면 맛있게 잘 먹겠습니다 &lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;마지막으로 이 강의를 완강한 이후로 어떤걸 하면 좋을지 방향성을 얘기해보겠습니다. 일단 코딩테스트를 기준으로 하면 이 강의 내용을 잘 따라왔을 때 떨어질래야 떨어질 수가 없습니다. 물론 제가 강의를 잘 만든 것도 있지만 응용 문제는 빼고 연습 문제와 체크된 기본 문제만 따져도 여러분이 푼 문제가 200문제가 넘습니다. 문제들을 제대로 안 풀고 그냥 진도 빼기에만 급급했거나 전부 다 풀이를 보고 대충 넘어간게 아니라면 강의를 듣기 전과 비교할 때 스스로 굉장히 실력이 많이 늘어있다는걸 느낄 수 있을 것 같습니다. 그렇긴한데 괜히 좀 찝찝해서 공부를 더 하고싶다면 문제집에 쌓여있는 수많은 문제들을 하나씩 풀기 전에 먼처 추천드릴게 있습니다. 문제집에 있는 문제를 풀 때에는 사실 굉장히 유리한 환경에서 생각을 해나갈 수 있었는데, 문제가 어떤 알고리즘을 요구하는지 알고 또 티어 표시를 켜두었다면 문제의 대략적인 난이도도 안 상태로 풀이를 고민할 수 있었습니다. 하지만 실전에서는 문제가 어떤 알고리즘을 필요로 하는지도, 대략적인 난이도도 알 수 없습니다. 그렇기 때문에 알고리즘 분류와 티어를 모른 채로 문제를 푸는 연습을 꼭 해보셔야 합니다. 제가 추천드리는건 우선 BOJ 설정에서 solved.ac 티어와 알고리즘 분류를 보이지 않게 설정한 후 대략 실버3에서 골드3 정도의 범위를 잡고 해당 범위의 문제 중에서 내가 아직 풀지 않은 문제를 맞힌 사람이 많은 순으로 하나씩 풀어보는겁니다. 이 때 실버3에서 골드3이라는 범위는 각자 상황에 맞게 더 낮추거나 높혀도 됩니다. 이런걸 랜덤 디펜스라고 부르기도 하는데, 이렇게 하나씩 해치우고 잘 떠오르지 않으면 풀이를 참고해보기도 하면서 풀어나가다보면 내가 약한 알고리즘이 무엇인지 감이 옵니다. 그 때 관련 단원의 내용을 복습하면서 해당 단원 문제집의 문제를 더 풀어보고 다시 랜덤 디펜스를 이어나가면 됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;만약 코딩테스트를 넘어 대회를 노리시는 분이라면 랜덤 디펜스와 함께 문제집에 있는 응용 문제들을 많이 풀어보면서 사고의 폭을 넓혀보시고 동시에 세그먼트 트리, 기하, 라빈 카프 알고리즘, 유량 문제, SCC, BCC, 게임 이론 등 다양한 알고리즘을 하나씩 익혀나가면 됩니다. 이 알고리즘들은 그냥 방금 제가 생각나는대로 막 적은거라 이 순서대로 공부를 하라는 뜻은 아닙니다. 저는 공부를 할 때 따로 책을 본 적은 없고 검색을 하면서 블로그를 통해 지식을 습득했는데, 이건 순전히 제가 그랬다는 것 뿐이니 각자 책을 보거나 강의를 보거나 하는 식으로 자신에게 맞는 방법을 찾으시면 됩니다. 그리고 코드포스나 앳코더도 꼭 활발히 참여해보시는걸 추천드립니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;사실 만들면서 제 알고리즘 강의를 &lt;span&gt;뉴비 시절 저에게 전해줄 수 있었다면 참 좋았을텐데 하는 생각을 많이 합니다. 지금은 이렇게 남한테 알고리즘을 가르친다고 강의도 찍어올리곤 하지만 한때는 저도 sync_with_stdio랑 cin.tie 안써서 시간 초과 받고, multiset에서 erase 썼더니 원소가 다 지워져서 당황하고 뭐 그런 시절이 있었죠. 그렇게 빙글빙글 헤매던 경험을 잘 갈무리해서 제 강의로 배우실 분들은 스트레이트로 쭉 달릴 수 있게 강의를 열심히 만들었습니다. 코딩테스트 합격도 합격이지만 제 강의를 통해&lt;/span&gt; ps 세계에 입문해서 대회에 수상하는 분이 나오면 정말 기쁠 것 같습니다. 그러면 긴 시간 고생 많으셨습니다. 다음에 또 인연이 닿는다면 다시 만납시다!&lt;/p&gt;</description>
      <category>강좌/실전 알고리즘</category>
      <author>BaaaaaaaaaaaaaaaaaaaaaaarkingDog</author>
      <guid isPermaLink="true">https://baaaaaaaaaaaaaaaaaaaaaaarkingdog.tistory.com/1059</guid>
      <comments>https://baaaaaaaaaaaaaaaaaaaaaaarkingdog.tistory.com/1059#entry1059comment</comments>
      <pubDate>Tue, 6 Sep 2022 23:28:54 +0900</pubDate>
    </item>
    <item>
      <title>몇 분 정도 고민한 후에도 감이 안오면 해설을 보는게 좋을까요? / 문제를 보고 어떤 알고리즘이 사용될지는 어떻게 알 수 있나요?</title>
      <link>https://baaaaaaaaaaaaaaaaaaaaaaarkingdog.tistory.com/1062</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;라는 질문에 대한 제 생각을 써봅니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;A.&lt;/b&gt; &lt;b&gt;몇 분 정도 고민한 후에도 감이 안오면 해설을 보는게 좋을까요?&lt;/b&gt;에 관해..&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;일단 한줄 요약으로 생각을 정리하면 알고리즘 공부 경험이 적다면/코딩테스트 통과만이 목표라면 답을 빨리 참고하고(30분 이내), 공부 경험이 많다면/대회에서 좋은 성적을 내고 싶다면 고민하는 시간을 길게 가져가는걸 추천드립니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;초보 단계에서는 주어진 문제가 내가 알고 있는 지식의 범위 내에서 풀린다는 확신을 하기가 어렵습니다. 이 지식의 범위에는 알고리즘에 대한 지식과 테크닉에 대한 지식이 모두 포함됩니다. 예를 들어 다익스트라 알고리즘을 공부한적 없는 사람이 최단 경로 문제를 풀어낼 수 있을리 없고, 설령 이분 탐색을 알더라도 매개 변수 탐색을 한 번도 본적이 없다면 매개 변수 탐색을 스스로 떠올리는건 불가능에 가깝습니다(지금에야 다익스트라 알고리즘과 매개 변수 탐색 모두 과장 조금 보태서 정보올림피아드를 공부하는 초등학생/중학생도 익힐 수 있는 내용이라 쉽게 보일 수 있지만 처음으로 세상에 등장할 때에는 세계적인 석학의 손에서 나왔습니다).&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;만약 주어진 문제가 내 지식 범위에서 풀 수 있는 문제라면 문제를 놓고 깊게 고민해보는게 문제 해결 능력을 기르는데에 좋은 훈련이 됩니다. 하지만 30분 정도 고민해도 실마리가 전혀 안잡힌다면 초보 단계에서는 내 지식 범위에서 풀 수 없는 문제일 가능성이 큽니다. 그렇기 때문에 고민하는 시간을 줄이고 풀이를 빠르게 확인하면서 알고리즘/테크닉을 습득하고 구현력을 늘려나가는걸 추천드립니다. 한편으로 내가 새로운 개념을 익히기 위해 의도적으로 어려운 문제를 풀고 있는 상황이라면 상관이 없지만, 그게 아니고 연습용으로 문제를 적당히 골라잡아 푸는데도 풀이를 모르겠어서 답을 봐야 하는 문제가 절반이 넘는 상황이라면 문제 난이도를 조금 더 낮춰서 연습을 하는걸 추천드립니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;하지만 어느 정도 알고리즘/테크닉을 많이 익힌 후에도 조금만 막히면 해설에 의존하는건 별로 좋은 방법이 아닙니다. 그렇게 되면 뭔가 아는게 많아진 것 같은 착각이 들지만 스스로 생각하는 힘을 기르지 못해 &lt;span&gt;새로운 문제를 봤을 때&lt;span&gt; 잘 풀어내지 못할 수 있습니다.&lt;/span&gt;&lt;/span&gt; 특히 불필요하게 티어에 집착을 하다보면 이런 경향을 보이기 쉬운데 공부를 하는 목적이 티어를 올리기 위함인지 아니면 대회에서 좋은 성적을 내기 위함인지 되짚어볼 필요가 있어보입니다. 노파심에 첨언하자면, PS 공부를 하는 목적이 반드시 대회 수상이어야 한다는 뜻은 아닙니다. 대회에 큰 뜻이 있다기보다는 단지 지적유희이거나 논문을 읽고 구현하며 고난이도 문제를 푸는 것에 더 흥미를 느낄 수 있습니다. 하지만 대회에서 수상을 하고 싶다면 스스로 생각하는 시간을 많이 가져보는걸 추천드립니다. 길게는 일주일 가까이 머릿속에 집어넣고 밥먹을때, 자기 직전에 등등 백그라운드에서 계속 돌리는 것도 좋습니다. 또 고급 개념들을 계속 익히는 것도 좋지만 적당한, 혹은 약간은 쉽지 않나 싶을 정도의 난이도의 문제를 풀어보는 것도 추천드리는데 꽤 낮은 난이도의 문제에서 의외로 고전하거나 새로운 깨달음을 얻어가는 일이 종종 있습니다. 저는 현재 코드포스 2410, solved.ac 기준으로 D3이고 P1 이상의 문제를 풀지 않으면 AC 레이팅에 변화가 없는 상황임에도 불구하고 때때로 골드 상위나 플래티넘 하위 정도의 문제에서 사고가 막힐 때도 있고 좋은걸 배워가기도 합니다. 가장 최근에 유튜브에 올린 2022 카카오 인턴십 코딩테스트를 푸는 영상에서도 (3번은 코딩 실수이니 제외하고) 4번, 5번 모두 대충 플래티넘 하위 정도의 난이도인데 한참 고생을 했고, 또 BOJ에서 최근에 푼 문제중 가장 인상 깊었던 문제는 P5인 &lt;a href=&quot;https://www.acmicpc.net/problem/20304&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;BOJ 20304번 - 비밀번호 제작&lt;/a&gt; 이네요. 물론 제가 접은지 대충 3년이 다되어가는 퇴1물인걸 감안하셔야 하지만 아무튼 그렇습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;B. &lt;b&gt;문제를 보고 어떤 알고리즘이 사용될지는 어떻게 알 수 있나요?&lt;/b&gt;에 관해..&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&quot;어떤 알고리즘을 사용해야 하는지 갈피를 바로 못 잡는 것&quot;에 대한 어려움은 공부를 아무리 많이 했어도 해소가 안된다고 생각합니다. 저도 어려운 문제를 풀어나가다보면 갈피를 못잡을 때가 많죠. 그렇기 때문에 이걸 완벽하게 해결할 수 있는 방법은 없다고 생각하지만 문제를 풀 때 제 머릿속에서 벌어지는 일을 정리해보면 도움이 될 것 같아서 정리를 해보겠습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1. 문제를 이해하고 요구하는 시간복잡도 계산(원소 탐색을 최대 50만번 하니까 아마 각 탐색 당 O(lgN) 혹은 O(1)이겠구나)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2. 문제에 필요한 연산과 주어진 조건을 보면서 사용되는 자료구조/알고리즘을 유추하기(앞뒤에서 삽입/삭제를 빠르게 해줘야 한다 -&amp;gt; deque,&amp;nbsp; 접두사나 접미사를 가지고 계산을 해야한다 -&amp;gt; 트라이, 그래프로 환원이 가능하고 간선의 가중치가 모두 같은 상황에서 최솟값을 구한다 -&amp;gt; BFS, 탐색 범위가 10^18과 같이 굉장히 큰데 결정 문제로 바꿀 수 있을 것 같다 -&amp;gt; Parametric search 등)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;3. 이전에 풀었던 비슷한 문제를 떠올리면서 착안&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;4. 여전히 감이 안오면 내가 알고 있는 알고리즘을 하나씩 넣어보면서 상황과 잘 맞아떨어지는지 확인&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;5. 이렇게까지 해도 모르겠으면 문제의 난이도를 슬쩍 확인한 후 난이도가 쉽다면 머리를 쥐어뜯으며 계속 고민, 난이도가 높다면 알고리즘 분류를 먼저 확인하거나 그냥 답을 참고함&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이런 느낌으로 진행합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그리고 이 과정에서 문제에 필요한 연산과 주어진 조건을 보면서 사용되는 자료구조/알고리즘을 잘 유추하기 위해서나 비슷한 문제로부터 착안을 해내기 위해서는 특정 알고리즘을 공부한 후에 다양한 응용 사례와 테크닉을 공부해야 합니다. 예를 들어 BFS만 하더라도 제일 기초는 flood fill이지만 여기서 출발해 거리 측정, 여러 시작점에서의 bfs, 서로 다른 종류에서 동시에 진행되는 bfs, 상하좌우 대신 knights의 움직임대로 bfs 등 수많은 바리에이션이 있죠. 처음 이런 응용 문제를 보고 혼자 힘으로 풀기는 어려울 수 있지만 일단 테크닉을 한 번 익히고 나면 잘 써먹을 수 있습니다. 그렇기 때문에 여력이 된다면 응용 문제를 계속 시도해보는게 좋습니다. 그리고 실전 환경과 같이 알고리즘 분류/난이도를 모른 채로 문제를 푸는 연습도 병행할 필요가 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;두 질문에 대한 답변을 총정리하면&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1. 알고리즘 공부 경험이 적다면/코딩테스트 통과만이 목표라면 답을 빨리 참고하고(30분 이내), 공부 경험이 많다면/대회에서 좋은 성적을 내고 싶다면 고민하는 시간을 길게 가지기&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2. 어느 정도 알고리즘/테크닉을 많이 익힌 후에는 조금만 막히더라도 해설에 의존하는 식으로 공부를 하지 말고 생각을 오래 해보기&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;3. 각 알고리즘의 응용 문제를 많이 풀어보기&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;4. 알고리즘 분류/난이도를 모른 채로 문제를 푸는 연습을 병행하기&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;입니다.&lt;/p&gt;</description>
      <category>알고리즘/ETC</category>
      <author>BaaaaaaaaaaaaaaaaaaaaaaarkingDog</author>
      <guid isPermaLink="true">https://baaaaaaaaaaaaaaaaaaaaaaarkingdog.tistory.com/1062</guid>
      <comments>https://baaaaaaaaaaaaaaaaaaaaaaarkingdog.tistory.com/1062#entry1062comment</comments>
      <pubDate>Wed, 31 Aug 2022 01:13:23 +0900</pubDate>
    </item>
    <item>
      <title>데프콘</title>
      <link>https://baaaaaaaaaaaaaaaaaaaaaaarkingdog.tistory.com/1061</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;어케저케 19년부터 4년 연속으로 데프콘 ctf에 참여합니다ㅎㅎ;; 미국 갈까말까 고민을 엄청 했는데 올해 너무 열심히 돌아다녀서 라스베가스까지 갈 용기가 나지 않아 얌전히 집에서 하기로 했습니다,,, 내년에는 갈 수 있겠죠....?&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;대회 시간은 토요일 오전 2시 - 오전 10시(인데 1시간 미뤄져서 3시 - 11시), 일요일 오전 2시 - 오전 10시, 월요일 오전 2시 - 오전 6시입니다. 월요일이 공휴일인게 정말 다행이네요.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1192&quot; data-origin-height=&quot;68&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/7eCkH/btrJAdW4iAs/naZKPM8jdS4uk3xh8iilWK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/7eCkH/btrJAdW4iAs/naZKPM8jdS4uk3xh8iilWK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/7eCkH/btrJAdW4iAs/naZKPM8jdS4uk3xh8iilWK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F7eCkH%2FbtrJAdW4iAs%2FnaZKPM8jdS4uk3xh8iilWK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1192&quot; height=&quot;68&quot; data-origin-width=&quot;1192&quot; data-origin-height=&quot;68&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;올해 룰에 적힌 얘기를 보니 올해도 뭔가 제대로 된 기여를 하기는 글러먹은것 같지만 그래도 하는데까진 해봐야죠. KoH이라도 할게 있으면 좋겠네여&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;올해는 e스포츠 식으로 1ㄷ1로 붙는 것도 한다는데 기대가 됩니다&amp;nbsp;&lt;a href=&quot;https://www.youtube.com/watch?v=DCFlJWVBfkk&quot;&gt;https://www.youtube.com/watch?v=DCFlJWVBfkk&lt;/a&gt;&amp;nbsp;&lt;/p&gt;
&lt;figure data-ke-type=&quot;video&quot; data-ke-style=&quot;alignCenter&quot; data-video-host=&quot;youtube&quot; data-video-url=&quot;https://www.youtube.com/watch?v=DCFlJWVBfkk&quot; data-video-thumbnail=&quot;https://scrap.kakaocdn.net/dn/S0C9E/hyPq0g7EdR/BPcwLMNfXsHDVBzNQRAKh0/img.jpg?width=1280&amp;amp;height=720&amp;amp;face=0_0_1280_720&quot; data-video-width=&quot;860&quot; data-video-height=&quot;484&quot; data-video-origin-width=&quot;860&quot; data-video-origin-height=&quot;484&quot; data-ke-mobilestyle=&quot;widthContent&quot;&gt;&lt;iframe src=&quot;https://www.youtube.com/embed/DCFlJWVBfkk&quot; width=&quot;860&quot; height=&quot;484&quot; frameborder=&quot;&quot; allowfullscreen=&quot;true&quot;&gt;&lt;/iframe&gt;
&lt;figcaption&gt;&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그럼 DiceGuesser ㅎㅇㅌ~&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>일상/ETC</category>
      <author>BaaaaaaaaaaaaaaaaaaaaaaarkingDog</author>
      <guid isPermaLink="true">https://baaaaaaaaaaaaaaaaaaaaaaarkingdog.tistory.com/1061</guid>
      <comments>https://baaaaaaaaaaaaaaaaaaaaaaarkingdog.tistory.com/1061#entry1061comment</comments>
      <pubDate>Sat, 13 Aug 2022 02:38:52 +0900</pubDate>
    </item>
    <item>
      <title>자바로 bfs나 큐/스택이 필요할 때..?</title>
      <link>https://baaaaaaaaaaaaaaaaaaaaaaarkingdog.tistory.com/1060</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://gall.dcinside.com/mgallery/board/view/?id=ps&amp;amp;no=26577&amp;amp;page=1&quot;&gt;https://gall.dcinside.com/mgallery/board/view/?id=ps&amp;amp;no=26577&amp;amp;page=1&lt;/a&gt;&amp;nbsp;&lt;/p&gt;
&lt;figure id=&quot;og_1659621421352&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;website&quot; data-og-title=&quot;오늘의 C++ 상식 - PS 마이너 갤러리&quot; data-og-description=&quot;자바에선 큐도 스택도 ArrayDeque를 사용하는 것이 좋다&quot; data-og-host=&quot;gall.dcinside.com&quot; data-og-source-url=&quot;https://gall.dcinside.com/mgallery/board/view/?id=ps&amp;amp;no=26577&amp;amp;page=1&quot; data-og-url=&quot;https://gall.dcinside.com/mgallery/board/view/?id=ps&amp;amp;no=26577&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/dmm5oN/hyPkIulNCY/25E2yPsMgGD4gk5u3nETek/img.png?width=550&amp;amp;height=350&amp;amp;face=119_105_428_182,https://scrap.kakaocdn.net/dn/45Rpx/hyPjl8B739/gWsdXSBUZdx7ZfVSSXrXI1/img.png?width=550&amp;amp;height=350&amp;amp;face=119_105_428_182,https://scrap.kakaocdn.net/dn/qhASq/hyPkLR9pxh/pxBaWw0bVHUH9vpF5dxtr0/img.png?width=550&amp;amp;height=350&amp;amp;face=119_105_428_182&quot;&gt;&lt;a href=&quot;https://gall.dcinside.com/mgallery/board/view/?id=ps&amp;amp;no=26577&amp;amp;page=1&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://gall.dcinside.com/mgallery/board/view/?id=ps&amp;amp;no=26577&amp;amp;page=1&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/dmm5oN/hyPkIulNCY/25E2yPsMgGD4gk5u3nETek/img.png?width=550&amp;amp;height=350&amp;amp;face=119_105_428_182,https://scrap.kakaocdn.net/dn/45Rpx/hyPjl8B739/gWsdXSBUZdx7ZfVSSXrXI1/img.png?width=550&amp;amp;height=350&amp;amp;face=119_105_428_182,https://scrap.kakaocdn.net/dn/qhASq/hyPkLR9pxh/pxBaWw0bVHUH9vpF5dxtr0/img.png?width=550&amp;amp;height=350&amp;amp;face=119_105_428_182');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;오늘의 C++ 상식 - PS 마이너 갤러리&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;자바에선 큐도 스택도 ArrayDeque를 사용하는 것이 좋다&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;gall.dcinside.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;자바에서 bfs같은거 짤 때 남들이 다 그렇게 하길래 늘 관성적으로 LinkedList로 했는데 자바에도 Deque이 있었네요...? 같은 O(1)이긴 하지만 LinkedList보다 Deque이 cache hit이 더 잘되어서 성능이 더 좋아서 Deque을 쓰는게 항상 더 좋을텐데 이거 저만 처음 안거 아니죠,,?&lt;/p&gt;</description>
      <category>알고리즘/ETC</category>
      <author>BaaaaaaaaaaaaaaaaaaaaaaarkingDog</author>
      <guid isPermaLink="true">https://baaaaaaaaaaaaaaaaaaaaaaarkingdog.tistory.com/1060</guid>
      <comments>https://baaaaaaaaaaaaaaaaaaaaaaarkingdog.tistory.com/1060#entry1060comment</comments>
      <pubDate>Thu, 4 Aug 2022 23:00:23 +0900</pubDate>
    </item>
    <item>
      <title>[실전 알고리즘] 0x1E강 - KMP</title>
      <link>https://baaaaaaaaaaaaaaaaaaaaaaarkingdog.tistory.com/1040</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;figure data-ke-type=&quot;video&quot; data-ke-style=&quot;alignCenter&quot; data-video-host=&quot;youtube&quot; data-video-url=&quot;https://www.youtube.com/watch?v=9bkbV-VANQ0&quot; data-video-thumbnail=&quot;https://scrap.kakaocdn.net/dn/Rxo9c/hyPhAKVemQ/JHa46URvkO0bpmjqdnVZBK/img.jpg?width=480&amp;amp;height=360&amp;amp;face=0_0_480_360&quot; data-video-width=&quot;480&quot; data-video-height=&quot;360&quot; data-video-origin-width=&quot;480&quot; data-video-origin-height=&quot;360&quot; data-ke-mobilestyle=&quot;widthContent&quot; data-original-url=&quot;&quot; data-video-title=&quot;&quot;&gt;&lt;iframe src=&quot;https://www.youtube.com/embed/9bkbV-VANQ0&quot; width=&quot;480&quot; height=&quot;360&quot; frameborder=&quot;&quot; allowfullscreen=&quot;true&quot;&gt;&lt;/iframe&gt;
&lt;figcaption style=&quot;display: none;&quot;&gt;&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/ew9I6m/btruQjQVtsc/dmuZ2VeMb8i9kSGO6Nnvxk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/ew9I6m/btruQjQVtsc/dmuZ2VeMb8i9kSGO6Nnvxk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/ew9I6m/btruQjQVtsc/dmuZ2VeMb8i9kSGO6Nnvxk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Few9I6m%2FbtruQjQVtsc%2FdmuZ2VeMb8i9kSGO6Nnvxk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1920&quot; height=&quot;1080&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;안녕하세요, 이번 시간부터 강의가 마칠 때 까지는 문자열 알고리즘을 다뤄보겠습니다. 미리 주의사항을 좀 알려드리자면 KMP의 경우 정말 헷갈립니다. 그렇기 때문에 이 강의를 보고 알듯말듯한 정도만 되면 성공이라고 생각하셔도 됩니다. 그리고 사실 KMP는 코딩테스트에 정말 드문 빈도로 나오는 알고리즘이라 나와도 기본 예제 수준으로만 나오지 응용을 필요로 하는 문제는 나올 가능성이 거의 없다고 볼 수 있는데, 뒤에서 다시 언급하겠지만 응용 없이 단순히 패턴 매칭만 필요하다면 g++에서는 strstr 함수가 KMP처럼 문자열과 패턴의 길이에 대한 선형 시간에 매칭 결과를 줘서 굳이 KMP를 몰라도 날로 먹을 수 있기도 합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;보통 학부 알고리즘 과목에서 KMP를 다루는 경우가 많아서 강의에 넣어두었지만 코딩테스트만 고려한다면 아예 응용까지 익힐게 아니고서는 굳이 KMP를 알아야 할 필요는 없습니다. 각자 상황에 맞춰서 내용을 취사선택하도록 합시다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bD4YnI/btrICZYCdJg/lTuJbc1PBQ13d564LVfZNk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bD4YnI/btrICZYCdJg/lTuJbc1PBQ13d564LVfZNk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bD4YnI/btrICZYCdJg/lTuJbc1PBQ13d564LVfZNk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbD4YnI%2FbtrICZYCdJg%2FlTuJbc1PBQ13d564LVfZNk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1920&quot; height=&quot;1080&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;목차는 가볍게 보고 넘어가겠습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/PM7En/btrH0QOLkNJ/0bVjgvEGoN5EfX1dKuQBD0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/PM7En/btrH0QOLkNJ/0bVjgvEGoN5EfX1dKuQBD0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/PM7En/btrH0QOLkNJ/0bVjgvEGoN5EfX1dKuQBD0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FPM7En%2FbtrH0QOLkNJ%2F0bVjgvEGoN5EfX1dKuQBD0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1920&quot; height=&quot;1080&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;KMP를&amp;nbsp;다루기&amp;nbsp;전에&amp;nbsp;이번&amp;nbsp;강의에서&amp;nbsp;사용할&amp;nbsp;용어들을&amp;nbsp;몇&amp;nbsp;가지&amp;nbsp;정의하고&amp;nbsp;가겠습니다.&amp;nbsp;첫&amp;nbsp;번째&amp;nbsp;줄과&amp;nbsp;같은&amp;nbsp;문자열의&amp;nbsp;slicing은&amp;nbsp;Python에서&amp;nbsp;사용하는&amp;nbsp;방식인데&amp;nbsp;본문에서&amp;nbsp;설명을&amp;nbsp;할&amp;nbsp;때도&amp;nbsp;저&amp;nbsp;표기가&amp;nbsp;간단해서&amp;nbsp;가져왔습니다.&amp;nbsp;혹시&amp;nbsp;Python을&amp;nbsp;이전에&amp;nbsp;배운&amp;nbsp;적&amp;nbsp;없어&amp;nbsp;S[a:b]라는&amp;nbsp;표현을&amp;nbsp;처음&amp;nbsp;보면&amp;nbsp;저기&amp;nbsp;적혀있는&amp;nbsp;정의를&amp;nbsp;잘&amp;nbsp;숙지해주세요.&amp;nbsp;S[a]는&amp;nbsp;포함하지만&amp;nbsp;S[b]는&amp;nbsp;포함하지&amp;nbsp;않습니다. &lt;br /&gt;&lt;br /&gt;|S|는 S의 길이를 의미합니다. 그리고 접두사와 접미사는 각각 문자열의 첫 문자를 포함하는 연속한 문자열, 문자열의 끝 문자를 포함하는 연속한 문자열을 의미합니다. slicing을&amp;nbsp;이용해&amp;nbsp;나타낸&amp;nbsp;정의도&amp;nbsp;한&amp;nbsp;번&amp;nbsp;이해해보도록&amp;nbsp;합시다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/pxJ5F/btrIH6CqsC9/BPU0TR0K11lbxHjyR5he4k/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/pxJ5F/btrIH6CqsC9/BPU0TR0K11lbxHjyR5he4k/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/pxJ5F/btrIH6CqsC9/BPU0TR0K11lbxHjyR5he4k/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FpxJ5F%2FbtrIH6CqsC9%2FBPU0TR0K11lbxHjyR5he4k%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1920&quot; height=&quot;1080&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이제&amp;nbsp;KMP&amp;nbsp;알고리즘이&amp;nbsp;무엇인지&amp;nbsp;알아봅시다.&amp;nbsp;KMP&amp;nbsp;알고리즘은&amp;nbsp;문자열&amp;nbsp;A&amp;nbsp;안에&amp;nbsp;문자열&amp;nbsp;B가&amp;nbsp;들어있는지를&amp;nbsp;판단하는&amp;nbsp;알고리즘입니다.&amp;nbsp;일단&amp;nbsp;KMP&amp;nbsp;알고리즘을&amp;nbsp;모르는&amp;nbsp;상황에서&amp;nbsp;A&amp;nbsp;안에&amp;nbsp;B가&amp;nbsp;있는지를&amp;nbsp;확인하려면&amp;nbsp;어떻게&amp;nbsp;해야할까요?&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/ccUnfP/btrIzFs2Xwt/iPXl0KVKsCN31SFMvY053k/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/ccUnfP/btrIzFs2Xwt/iPXl0KVKsCN31SFMvY053k/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/ccUnfP/btrIzFs2Xwt/iPXl0KVKsCN31SFMvY053k/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FccUnfP%2FbtrIzFs2Xwt%2FiPXl0KVKsCN31SFMvY053k%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1920&quot; height=&quot;1080&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;구현하는&amp;nbsp;방법은&amp;nbsp;간단합니다.&amp;nbsp;A의&amp;nbsp;각&amp;nbsp;위치별로&amp;nbsp;확인을&amp;nbsp;하면&amp;nbsp;됩니다.&amp;nbsp;먼저&amp;nbsp;A의&amp;nbsp;제일&amp;nbsp;앞부분이&amp;nbsp;B와&amp;nbsp;일치하는지&amp;nbsp;확인하는데&amp;nbsp;맨&amp;nbsp;첫글자부터&amp;nbsp;다릅니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dIcnjX/btrIywKceol/3NRK4kEu6RhCvknvSKej10/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dIcnjX/btrIywKceol/3NRK4kEu6RhCvknvSKej10/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dIcnjX/btrIywKceol/3NRK4kEu6RhCvknvSKej10/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdIcnjX%2FbtrIywKceol%2F3NRK4kEu6RhCvknvSKej10%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1920&quot; height=&quot;1080&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;A의 2번째 글자부터 확인했는데 또 다릅니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/ZHB04/btrIEbLfpFx/SzTKXIGFqQ10nFKe5exG4K/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/ZHB04/btrIEbLfpFx/SzTKXIGFqQ10nFKe5exG4K/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/ZHB04/btrIEbLfpFx/SzTKXIGFqQ10nFKe5exG4K/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FZHB04%2FbtrIEbLfpFx%2FSzTKXIGFqQ10nFKe5exG4K%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1920&quot; height=&quot;1080&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;3번째도 다릅니다. 뒤는 설명 없이 쭉 보여드리겠습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/LC38G/btrIyYTTaeU/WgoWaS68wdgzkDQAjOS2ik/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/LC38G/btrIyYTTaeU/WgoWaS68wdgzkDQAjOS2ik/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/LC38G/btrIyYTTaeU/WgoWaS68wdgzkDQAjOS2ik/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FLC38G%2FbtrIyYTTaeU%2FWgoWaS68wdgzkDQAjOS2ik%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1920&quot; height=&quot;1080&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/mizcG/btrIzEnmeSO/2HcNCR4Uhlh0HVwoyJAv6k/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/mizcG/btrIzEnmeSO/2HcNCR4Uhlh0HVwoyJAv6k/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/mizcG/btrIzEnmeSO/2HcNCR4Uhlh0HVwoyJAv6k/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FmizcG%2FbtrIzEnmeSO%2F2HcNCR4Uhlh0HVwoyJAv6k%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1920&quot; height=&quot;1080&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/mOkLy/btrIzE1WwKV/xHjwr46K2YkRzVXCFlS9g1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/mOkLy/btrIzE1WwKV/xHjwr46K2YkRzVXCFlS9g1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/mOkLy/btrIzE1WwKV/xHjwr46K2YkRzVXCFlS9g1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FmOkLy%2FbtrIzE1WwKV%2FxHjwr46K2YkRzVXCFlS9g1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1920&quot; height=&quot;1080&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bK2jke/btrIEb5z8xI/9n8u1aEch6NQExxFU5g4k0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bK2jke/btrIEb5z8xI/9n8u1aEch6NQExxFU5g4k0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bK2jke/btrIEb5z8xI/9n8u1aEch6NQExxFU5g4k0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbK2jke%2FbtrIEb5z8xI%2F9n8u1aEch6NQExxFU5g4k0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1920&quot; height=&quot;1080&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/BMd64/btrIH5Q3xJX/kPDJr8JaXE8SWXrU89R0zk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/BMd64/btrIH5Q3xJX/kPDJr8JaXE8SWXrU89R0zk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/BMd64/btrIH5Q3xJX/kPDJr8JaXE8SWXrU89R0zk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FBMd64%2FbtrIH5Q3xJX%2FkPDJr8JaXE8SWXrU89R0zk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1920&quot; height=&quot;1080&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;찾았습니다. A 안에는 B가 있었습니다. 이런 식으로 구현을 하면 됩니다. 강의를 지금까지 들어왔다면 이 정도는 당연히 구현을 할 수 있겠지만 그래도 제 코드를 한 번 보여드리겠습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cendoN/btrIH5XO8y5/wqiz5Dz6731VbVFT8lg5n1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cendoN/btrIH5XO8y5/wqiz5Dz6731VbVFT8lg5n1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cendoN/btrIH5XO8y5/wqiz5Dz6731VbVFT8lg5n1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcendoN%2FbtrIH5XO8y5%2Fwqiz5Dz6731VbVFT8lg5n1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1920&quot; height=&quot;1080&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;02번째&amp;nbsp;줄에서&amp;nbsp;(int)로&amp;nbsp;형변환을&amp;nbsp;하지&amp;nbsp;않으면&amp;nbsp;size&amp;nbsp;멤버&amp;nbsp;함수가&amp;nbsp;unsigned&amp;nbsp;int&amp;nbsp;자료형이기&amp;nbsp;때문에&amp;nbsp;개판이&amp;nbsp;날&amp;nbsp;수&amp;nbsp;있다는건&amp;nbsp;늘&amp;nbsp;주의를&amp;nbsp;해주어야&amp;nbsp;하고&amp;nbsp;그&amp;nbsp;외에&amp;nbsp;딱히&amp;nbsp;코드에서&amp;nbsp;설명이&amp;nbsp;필요한&amp;nbsp;부분은&amp;nbsp;없어보입니다. &lt;br /&gt;&lt;br /&gt;이 방법은 단순하면서도 일반적인 상황에서 매우 효율적으로 동작하기 때문에 보통 각 언어에서 패턴 매칭 문제를 해결하는 내장 함수는 이런식으로 구현이 되어있습니다. 물론 여기서 약간의 휴리스틱이 들어가있을 수는 있습니다. 그런데 이 구현의 시간복잡도는 최악의 경우 얼마일까요? 시간복잡도가 최악이 되는 A, B 모양을 고민해봅시다. 비단 지금뿐만 아니라 다른 상황에서도 본인의 코드에 대해 최악의 경우를 고민해보는건 코드의 시간복잡도를 분석할 때에도, 반례를 잡아낼 때에도 아주 큰 도움이 됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/TqWMp/btrIH6h7SX9/VLG5V8s7kykK2Mx1yTMSPK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/TqWMp/btrIH6h7SX9/VLG5V8s7kykK2Mx1yTMSPK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/TqWMp/btrIH6h7SX9/VLG5V8s7kykK2Mx1yTMSPK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FTqWMp%2FbtrIH6h7SX9%2FVLG5V8s7kykK2Mx1yTMSPK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1920&quot; height=&quot;1080&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;지금&amp;nbsp;이&amp;nbsp;예시가&amp;nbsp;최악의&amp;nbsp;예시입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/b9xeBs/btrIGzx6TUt/6p1gYpQsQgB0YqjkiZdtG0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/b9xeBs/btrIGzx6TUt/6p1gYpQsQgB0YqjkiZdtG0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/b9xeBs/btrIGzx6TUt/6p1gYpQsQgB0YqjkiZdtG0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fb9xeBs%2FbtrIGzx6TUt%2F6p1gYpQsQgB0YqjkiZdtG0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1920&quot; height=&quot;1080&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;끝까지 가고 나서야 일치하지 않음을 알게되고&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/b15PQF/btrIEdhZJn9/DxwuWkkz763WU9QHwdzilK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/b15PQF/btrIEdhZJn9/DxwuWkkz763WU9QHwdzilK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/b15PQF/btrIEdhZJn9/DxwuWkkz763WU9QHwdzilK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fb15PQF%2FbtrIEdhZJn9%2FDxwuWkkz763WU9QHwdzilK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1920&quot; height=&quot;1080&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff;&quot;&gt;한 칸 옮겨서도 마찬가지고&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/omzsQ/btrIEXTx7ra/a3UhD3r9PqhD17JSDLlh4K/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/omzsQ/btrIEXTx7ra/a3UhD3r9PqhD17JSDLlh4K/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/omzsQ/btrIEXTx7ra/a3UhD3r9PqhD17JSDLlh4K/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FomzsQ%2FbtrIEXTx7ra%2Fa3UhD3r9PqhD17JSDLlh4K%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1920&quot; height=&quot;1080&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;끝날때까지 쭉 그렇습니다. 즉 최악의 경우 O(|A| &amp;times; |B|)에 동작합니다. 이렇게 O(|A| &amp;times; |B|)에 동작하는건 지금처럼 사실상 의도적으로 만든 매우 특수한 입력에서 벌어지는 일이고 일반적인 상황에서는 매 위치마다 O(|B|)에 걸쳐 비교를 하는 일이 잘 생기지 않지만 잘 아시다시피 알고리즘 문제에서는 가장 시간이 오래 걸리는, 즉 최악의 경우를 고려해야 하기 때문에 이를테면 A, B의 길이가 각각 최대 100만인 것과 같이 특수한 경우에서는 지금의 방법으로 해결을 할 수가 없습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bVS91b/btrIEYLHc9g/Q7jEPXJPOhz2wsfTuASdP0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bVS91b/btrIEYLHc9g/Q7jEPXJPOhz2wsfTuASdP0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bVS91b/btrIEYLHc9g/Q7jEPXJPOhz2wsfTuASdP0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbVS91b%2FbtrIEYLHc9g%2FQ7jEPXJPOhz2wsfTuASdP0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1920&quot; height=&quot;1080&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그러면&amp;nbsp;KMP&amp;nbsp;알고리즘이&amp;nbsp;뭐냐고&amp;nbsp;했을&amp;nbsp;때&amp;nbsp;KMP&amp;nbsp;알고리즘은&amp;nbsp;패턴&amp;nbsp;매칭&amp;nbsp;문제를&amp;nbsp;O(|A|&amp;nbsp;+&amp;nbsp;|B|)에&amp;nbsp;해결할&amp;nbsp;수&amp;nbsp;있게&amp;nbsp;해주는&amp;nbsp;기적의&amp;nbsp;알고리즘입니다.&amp;nbsp;그리고&amp;nbsp;KMP로&amp;nbsp;검색해서&amp;nbsp;다른&amp;nbsp;블로그들을&amp;nbsp;확인해보시면&amp;nbsp;알겠지만&amp;nbsp;공통적으로&amp;nbsp;적혀있는&amp;nbsp;얘기가&amp;nbsp;KMP는&amp;nbsp;굉장히&amp;nbsp;이해하기&amp;nbsp;어렵고&amp;nbsp;또&amp;nbsp;헷갈린다는&amp;nbsp;얘기입니다.&amp;nbsp;이번에&amp;nbsp;강의&amp;nbsp;자료를&amp;nbsp;만들면서도&amp;nbsp;어떻게&amp;nbsp;해야&amp;nbsp;보는&amp;nbsp;사람에게&amp;nbsp;이해를&amp;nbsp;잘&amp;nbsp;시킬&amp;nbsp;수&amp;nbsp;있을까&amp;nbsp;아주&amp;nbsp;고민을&amp;nbsp;많이&amp;nbsp;했습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bHxQ0D/btrIEXzdhn1/PGCVGMiJpQGujTsiVIkmN0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bHxQ0D/btrIEXzdhn1/PGCVGMiJpQGujTsiVIkmN0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bHxQ0D/btrIEXzdhn1/PGCVGMiJpQGujTsiVIkmN0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbHxQ0D%2FbtrIEXzdhn1%2FPGCVGMiJpQGujTsiVIkmN0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1920&quot; height=&quot;1080&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;KMP 알고리즘을 이해하기에 앞서 KMP에서 쓰이는 실패함수를 알면 KMP를 이해하는데 도움이 됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;일단 실패 함수 F(x)는 문자열 S[0:x+1]에서 자기 자신을 제외하고 접두사와 접미사가 일치하는 최대 길이로 정의됩니다. 뭔소린지 이해가 안가면 그거 당신 잘못 아닙니다. 아 물론 제 잘못도 아닙니다. 그냥 그럴 수 있습니다. 저도 언제였는지 솔직히 기억은 안나지만 아무튼 KMP를 처음 배울 때 말 그대로 뇌정지가 심하게 왔었습니다. 예시를 통해 이해를 하실 수 있도록 최대한 친절하게 예시를 구성했으니 같이 봅시다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;F(2)를 같이 구해볼건데, F(2)는 S[0:3]에서 자기 자신을 제외하고 접두사와 접미사가 일치하는 최대 길이입니다. 이말인즉슨 앞 3글자인 ABA에서 접두사와 접미사가 일치하는 최대 길이를 구하겠다는 의미입니다. F(x)가 문자열 S의 앞 x글자가 아니라 앞 x+1글자에서 접두사와 접미사의 최대 일치 길이라는 점을 꼭 기억해주세요. 먼저 F(2)가 2인지를 확인하려면 ABA에서 길이가 2인 접두사 AB와 접미사 BA가 일치하는지를 봅니다. AB와 BA는 다르기 때문에 F(2)는 2가 아닙니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cueh4I/btrJqLrkGfW/ZjqRK1NWSzQOAy0ryq9ey0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cueh4I/btrJqLrkGfW/ZjqRK1NWSzQOAy0ryq9ey0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cueh4I/btrJqLrkGfW/ZjqRK1NWSzQOAy0ryq9ey0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fcueh4I%2FbtrJqLrkGfW%2FZjqRK1NWSzQOAy0ryq9ey0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1920&quot; height=&quot;1080&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다음으로 F(2) = 1인지 확인해보면 ABA에서 길이가 1인 접두사는 A이고 접미사도 A이어서 F(2)는 1입니다. 최대 길이를 구하고 싶기 때문에 지금 한 것과 같이 2부터 차례로 시도해봐야겠죠.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bZo2Mt/btrJqmk3Qtq/JXEnXKDccMlEsTOamBZm01/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bZo2Mt/btrJqmk3Qtq/JXEnXKDccMlEsTOamBZm01/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bZo2Mt/btrJqmk3Qtq/JXEnXKDccMlEsTOamBZm01/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbZo2Mt%2FbtrJqmk3Qtq%2FJXEnXKDccMlEsTOamBZm01%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1920&quot; height=&quot;1080&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그러면&amp;nbsp;이&amp;nbsp;실패함수를&amp;nbsp;어떻게&amp;nbsp;구하는걸까요?&amp;nbsp;사실&amp;nbsp;아직&amp;nbsp;실패함수가&amp;nbsp;왜&amp;nbsp;필요한지조차&amp;nbsp;제대로&amp;nbsp;다루지&amp;nbsp;않았지만&amp;nbsp;그건&amp;nbsp;천천히&amp;nbsp;이해하는&amp;nbsp;것으로&amp;nbsp;합시다. &lt;br /&gt;&lt;br /&gt;현재 저희가 시도할 수 있는 가장 쉬운 방법은 예를 들어 F(5)을 구하고 싶다고 할 때 F(5) = 5인지 확인하고, 일치하지 않으면 F(5) = 4인지 확인하고, 이렇게 하나하나 확인하는 방법입니다. F(5) = 5인지 확인해보면 ABABCA에서 길이가 5인 접두사 ABABC와 접미사 BABCA가 일치하는지를 봅니다. ABABC와 BABCA는 다르기 때문에 F(5)는 5가 아닙니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/GdH8h/btrJn7h8kN3/h0wFh5MOkgsW0N9by7CVCk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/GdH8h/btrJn7h8kN3/h0wFh5MOkgsW0N9by7CVCk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/GdH8h/btrJn7h8kN3/h0wFh5MOkgsW0N9by7CVCk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FGdH8h%2FbtrJn7h8kN3%2Fh0wFh5MOkgsW0N9by7CVCk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1920&quot; height=&quot;1080&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;F(5) = 4인지 확인해보면 비슷한 분석을 통해서 F(5)은 4가 아님을 알 수 있습니다. 앞 두 글자는 같았는데 약간 아깝네요. 이 뒤는 설명없이 바로 보여드리겠습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/PE84m/btrJn7PXsIi/6WmkMYokFHuNOEsu5kyAi1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/PE84m/btrJn7PXsIi/6WmkMYokFHuNOEsu5kyAi1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/PE84m/btrJn7PXsIi/6WmkMYokFHuNOEsu5kyAi1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FPE84m%2FbtrJn7PXsIi%2F6WmkMYokFHuNOEsu5kyAi1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1920&quot; height=&quot;1080&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/Ohxj0/btrJrf6N4V3/QGZGvmNpv45y82bor7AIXK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/Ohxj0/btrJrf6N4V3/QGZGvmNpv45y82bor7AIXK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/Ohxj0/btrJrf6N4V3/QGZGvmNpv45y82bor7AIXK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FOhxj0%2FbtrJrf6N4V3%2FQGZGvmNpv45y82bor7AIXK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1920&quot; height=&quot;1080&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/FwyZB/btrJpftr1ZN/C89GGBKpX4kxTKv7sqlKpK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/FwyZB/btrJpftr1ZN/C89GGBKpX4kxTKv7sqlKpK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/FwyZB/btrJpftr1ZN/C89GGBKpX4kxTKv7sqlKpK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FFwyZB%2FbtrJpftr1ZN%2FC89GGBKpX4kxTKv7sqlKpK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1920&quot; height=&quot;1080&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이렇게 F(5)가 1인지까지 쭉 확인을 해서 F(5) = 1임을 알게 되었습니다. 이런 식으로 계산을 하면 각 F(x)에 대해 최악의 경우 O(|S|^2)의 연산이 필요하기 때문에 시간복잡도는 O(|S|^3)입니다. 그런데 전체 F를 무려 O(|S|)에 구하는 방법이 있습니다. 전혀 감이 안오시겠지만 같이 알아보겠습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;전체 F를&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;O(|S|^3)가 아닌&lt;/span&gt; O(|S|)에 구하려면 마치 다이나믹 프로그래밍과 같이 각 F의 값을 구할 때 이전의 F 값을 활용할 수 있어야 합니다. 일단 F(5)는 앞에서 같이 계산한 것 처럼 1임을 알고 있습니다. 이 상황에서 F(6)를 어떻게 구할 수 있는지 같이 고민해보겠습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bOOWvZ/btrIBUcaDvZ/SS2BvHNmK8gtPMVuKwjMPk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bOOWvZ/btrIBUcaDvZ/SS2BvHNmK8gtPMVuKwjMPk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bOOWvZ/btrIBUcaDvZ/SS2BvHNmK8gtPMVuKwjMPk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbOOWvZ%2FbtrIBUcaDvZ%2FSS2BvHNmK8gtPMVuKwjMPk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1920&quot; height=&quot;1080&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;지금 이 그림에서 F(6)를 계산할 때 F(5)을 어떻게 이용할 수 있는지를 표시해뒀습니다. F(6)을 구할 때 이전에 하던 것 처럼 F(6) = 6인지, F(6) = 5인지 차례로 확인할 필요가 없고 F(5)가 1이라는 정보를 그대로 가져올 수 있습니다. 그렇게 되면 밑의 문자열을 움직일 필요가 없이 위와 아래 각각에서 이전에 확인한 문자열들의 다음 칸에 해당하는 두 글자가 일치하는지 확인하면 됩니다. 그 두 글자는 그림에 연한 초록과 진한 초록으로 표시해두었습니다. 두 글자가 B로 일치하기 때문에 최종적으로 접두사와 접미사의 앞 2글자가 같음을 알 수 있습니다. 이렇게 이전에 계산했던 정보를 재활용할 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cbmW7f/btrIA2n2eU5/41YWzH4VL1x4MBd1jMGARK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cbmW7f/btrIA2n2eU5/41YWzH4VL1x4MBd1jMGARK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cbmW7f/btrIA2n2eU5/41YWzH4VL1x4MBd1jMGARK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcbmW7f%2FbtrIA2n2eU5%2F41YWzH4VL1x4MBd1jMGARK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1920&quot; height=&quot;1080&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그런데 엄밀하게 말해서 F(5)로부터 F(6)에서&amp;nbsp;&lt;span&gt;접두사와 접미사의 앞 2글자가 같다는건 알아냈지만 그렇다고 해서 F(6)을 2로 바로 확정지을 수는 없습니다. 2글자보다 더 많이 일치해서 F(6)이 2보다 클 수는 없는지를 확인해야 하기 때문입니다. 하지만 사실 논리적으로 생각해보면 F(5) = 1라는 사실로부터 F(6)이 2보다 클 수 없다는건 자동으로 따라오게 됩니다. 왜 그런지를 같이 살펴보겠습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/nYXP4/btrIyxPPO4z/SuT0eA9KVchO5XOcY3TgvK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/nYXP4/btrIyxPPO4z/SuT0eA9KVchO5XOcY3TgvK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/nYXP4/btrIyxPPO4z/SuT0eA9KVchO5XOcY3TgvK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FnYXP4%2FbtrIyxPPO4z%2FSuT0eA9KVchO5XOcY3TgvK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1920&quot; height=&quot;1080&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;S에 A나 B 같은 글자가 적혀있으면 오히려 혼동을 줄 수 있어서 글자를 빼놓고 설명을 진행해보겠습니다. 우리는 F(6)이 2보다 클 수 없다는걸 귀류법으로 보이려고 합니다. 만약 F(6)이 2보다 크다면 적어도 S[0:7]에서 앞 3글자와 뒷 3글자가 일치한다는 의미니까 위의 그림과 같이 S[0:3] = S[4:7]입니다. &lt;/span&gt;&lt;span&gt;그런데 그렇게 되면 S[0:2]와 S[4:6]이 일치하기 때문에 F(5)가 최소 2 이상입니다. 이미 F(5) = 1이라는 사실을 알고 있기 때문에 F(5)가 최소 2 이상인 상황은 분명히 모순입니다. 그렇기 때문에 F(6)이 2보다 클 수는 없고, 최종적으로 F(6) = 2임을 알 수 있습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;지금까지 한 얘기를 일반화하면 우리는 F(k)을 구할 때 F(k-1)의 값을 이용할 수 있는데, F(k)은 최대 F(k-1)+1입니다. 그렇기 때문에 지금 이 예시처럼 만약 S[F(k-1)]와 S[k]을 비교해서 두 글자가 일치한다면 바로 F(k) = F(k-1) + 1로 확정지을 수 있습니다. 한편 F(k)을 구할 때 왜 S[F(k-1)]와 S[k] 이 두 글자를 비교하는지 약간 헷갈릴 수 있습니다. 이런 인덱스 문제가 사실 매번 굉장히 사람을 헷갈리게 만드는 요소이긴 하지만 특히 KMP를 구현할 때 이걸 잘 이해해야 코드를 받아들이기 쉬워서 같이 살펴보겠습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/XN5u5/btrQV0HFTfY/4o5kJc4ELwxVsKTH0DeNKK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/XN5u5/btrQV0HFTfY/4o5kJc4ELwxVsKTH0DeNKK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/XN5u5/btrQV0HFTfY/4o5kJc4ELwxVsKTH0DeNKK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FXN5u5%2FbtrQV0HFTfY%2F4o5kJc4ELwxVsKTH0DeNKK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1920&quot; height=&quot;1080&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;일단 F(k)를 구하는 과정을 보면 이런식으로 일치하는 구간을 찾게 되고, 각 칸의 인덱스는 위에 적힌 것과 같습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/yI4c4/btrQRnrBLL9/wzBTQYohIHb1JunCdvDMIK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/yI4c4/btrQRnrBLL9/wzBTQYohIHb1JunCdvDMIK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/yI4c4/btrQRnrBLL9/wzBTQYohIHb1JunCdvDMIK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FyI4c4%2FbtrQRnrBLL9%2FwzBTQYohIHb1JunCdvDMIK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1920&quot; height=&quot;1080&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 상황에서 윗쪽과 아랫쪽을 둘 다 한 칸씩 늘리면 인덱스가 각각 k와 F(k-1)이 되어서 결론적으로&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;S[F(k-1)]과 S[k]를 비교하면 됩니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/IYYv7/btrIA1ii95N/02Kb7BJEg5h8JtbkUVioFk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/IYYv7/btrIA1ii95N/02Kb7BJEg5h8JtbkUVioFk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/IYYv7/btrIA1ii95N/02Kb7BJEg5h8JtbkUVioFk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FIYYv7%2FbtrIA1ii95N%2F02Kb7BJEg5h8JtbkUVioFk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1920&quot; height=&quot;1080&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 관찰을 통해 F 배열을 처음부터 쭉 채워봅시다. 사실 지금 &lt;span&gt;S[F(k-1)]과 S[k]가 일치하지 않을 때에 대해서는 알려드리지 않았는데, 조금 있다가 적절한 예시가 나오면 &lt;/span&gt;&lt;span&gt;같이 살펴보도록 하겠습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;먼저 F(0)은 F의 정의상 S[0:1] = &quot;A&quot;에서 접두사와 접미사가 일치하는 최대 길이이니 자명하게 0입니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/UysAj/btrIyv5wZmv/sUUNY7eHulfkFalvVfNW21/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/UysAj/btrIyv5wZmv/sUUNY7eHulfkFalvVfNW21/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/UysAj/btrIyv5wZmv/sUUNY7eHulfkFalvVfNW21/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FUysAj%2FbtrIyv5wZmv%2FsUUNY7eHulfkFalvVfNW21%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1920&quot; height=&quot;1080&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그 다음 F(1)도 계산해보면 &quot;AB&quot;에서 접두사와 접미사가 일치하는 최대 길이가 없어서 0입니다. S[F(0)] = S[0]과 S[1]을 비교해보면 둘의 값이 달라서 원래는 뭔가 다른 조치가 필요합니다. 하지만 예시가 별로 예쁘지 않아서 여기까지는 그냥 그런가보다 하고 생각하고 넘어가주세요.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bQcPxI/btrIzFNiVIr/9ZMhUj9abUhh0adqlvKEkK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bQcPxI/btrIzFNiVIr/9ZMhUj9abUhh0adqlvKEkK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bQcPxI/btrIzFNiVIr/9ZMhUj9abUhh0adqlvKEkK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbQcPxI%2FbtrIzFNiVIr%2F9ZMhUj9abUhh0adqlvKEkK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1920&quot; height=&quot;1080&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;F(2)를 구하기 위해서 &lt;span&gt;S[F(1)] = S[0]과 S[2]를 비교해보면 둘은 일치합니다. 그러면 그전의 F 값인 F(1) = 0에서 뒤에 한 글자가 붙는게 F(2)이고, 그말인즉슨 F(2) = F[1] + 1입니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/eeSorl/btrIBTEkNjV/hmkXZAN2XpdR4yrOrxaxL0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/eeSorl/btrIBTEkNjV/hmkXZAN2XpdR4yrOrxaxL0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/eeSorl/btrIBTEkNjV/hmkXZAN2XpdR4yrOrxaxL0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FeeSorl%2FbtrIBTEkNjV%2FhmkXZAN2XpdR4yrOrxaxL0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1920&quot; height=&quot;1080&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다음으로 F(3)을 구할땐 F(2)의 결과에서 글자 1개씩을 붙일 수 있는지 봅니다. S[F(2)] = S[1]과 S[3]을 비교해보면 둘은 일치하기 때문에 F(3) = F(2) + 1 = 2입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/U4Sru/btrIyZrJmOM/YVh5V2VpIp8Q4ucHOZhRX1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/U4Sru/btrIyZrJmOM/YVh5V2VpIp8Q4ucHOZhRX1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/U4Sru/btrIyZrJmOM/YVh5V2VpIp8Q4ucHOZhRX1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FU4Sru%2FbtrIyZrJmOM%2FYVh5V2VpIp8Q4ucHOZhRX1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1920&quot; height=&quot;1080&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이런 식으로 F의 마지막 값은 제외하고 다 채워두었다고 해봅시다. 드디어 마지막 칸을 채울 차례입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/OgjZE/btrIA1JpNWW/fTOLt5AVkrQvY5aa8LwyKk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/OgjZE/btrIA1JpNWW/fTOLt5AVkrQvY5aa8LwyKk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/OgjZE/btrIA1JpNWW/fTOLt5AVkrQvY5aa8LwyKk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FOgjZE%2FbtrIA1JpNWW%2FfTOLt5AVkrQvY5aa8LwyKk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1920&quot; height=&quot;1080&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;만약 S[F(8)] = S[4]와 S[9]가 일치했다면 F(9) = F(8) + 1 = 5였겠지만 아쉽게도 두 글자가 다릅니다. 그러면 우리는 F(9) 값을 찾기 위해 아래에 있는 문자열을 오른쪽으로 밀어야합니다. 한 칸씩 밀면서 확인을 하면 F(9)가 4인지, 3인지, 2인지, 1인지를 확인할 수 있습니다. 그런데 이 때 이미 구해놓은 값을 가지고 영리하게 밀 수 있다는게 실패 함수를 효율적으로 구하는 키 포인트입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bKUjKr/btrIGx77y5h/MMQ2lYoMykw745JdGx54f0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bKUjKr/btrIGx77y5h/MMQ2lYoMykw745JdGx54f0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bKUjKr/btrIGx77y5h/MMQ2lYoMykw745JdGx54f0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbKUjKr%2FbtrIGx77y5h%2FMMQ2lYoMykw745JdGx54f0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1920&quot; height=&quot;1080&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;제가 영리하게 미는 과정을 이해하는데에 필요한 값들에 전부 초록색으로 표시해두었는데 아마 전혀 이해가 안가시겠죠? 정상입니다. 하지만 저는 꿋꿋이 설명을 할테니 행운을 빕니다. 한번 듣고 이해가 안가더라도 한 다섯번 곱씹어보면 이해가 될 수 있습니다. 자 일단 F(8) = 4이기 때문에 그 전에 접두사 4글자와 접미사 4글자는 일치하던 상태였습니다. 하지만 한 글자를 추가하려고 하니 두 글자가 달라서 불가능한 상황이었습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/A73SE/btrIzDWitky/Lrekbg23ztr9IzLRpjBdrK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/A73SE/btrIzDWitky/Lrekbg23ztr9IzLRpjBdrK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/A73SE/btrIzDWitky/Lrekbg23ztr9IzLRpjBdrK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FA73SE%2FbtrIzDWitky%2FLrekbg23ztr9IzLRpjBdrK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1920&quot; height=&quot;1080&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 상황에서 그냥 늘 하던대로 별 생각없이 아래에 있는 문자열을 한 칸 오른쪽으로 밀어서 F(9) = 4인지 비교를 할 수도 있긴 하지만&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dDrvyF/btrIEYLHmoo/e6zWFvXFYiKekIdyUKngmk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dDrvyF/btrIEYLHmoo/e6zWFvXFYiKekIdyUKngmk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dDrvyF/btrIEYLHmoo/e6zWFvXFYiKekIdyUKngmk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdDrvyF%2FbtrIEYLHmoo%2Fe6zWFvXFYiKekIdyUKngmk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1920&quot; height=&quot;1080&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;오히려 원래 문자열은 잠깐 제쳐두고 이렇게 2개를 놓고 보겠습니다. 또 여기서 F(8) = 4로부터 알고있는 정보를 같이 표시해보면, 그 중에서도 초록색으로 표시된 부분을 아주 정말 주의깊게 들여다보면 한 100명 중에 1명은 아하 하고 깨달음을 얻을수도 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bylARv/btrIGxNN9T3/bfFM98AYfkgln0Heob2NdK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bylARv/btrIGxNN9T3/bfFM98AYfkgln0Heob2NdK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bylARv/btrIGxNN9T3/bfFM98AYfkgln0Heob2NdK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbylARv%2FbtrIGxNN9T3%2FbfFM98AYfkgln0Heob2NdK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1920&quot; height=&quot;1080&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;아직 전혀 깨달음이 오지 않은 나머지 분들을 위해 좀 더 설명을 해보겠습니다. 우리는 F(3) = 2임을 미리 알고 있습니다. 또 F(3) = 2가 의미하는 바는 바로 저기 오른쪽 위에 그림으로 표시한 부분입니다. 접두사와 접미사의 3글자가 겹치지는 않지만 2글자는 겹친다는 의미이죠.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bqclos/btrIGxAhonK/R20tdk5pnWpnmiScz7Ovik/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bqclos/btrIGxAhonK/R20tdk5pnWpnmiScz7Ovik/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bqclos/btrIGxAhonK/R20tdk5pnWpnmiScz7Ovik/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fbqclos%2FbtrIGxAhonK%2FR20tdk5pnWpnmiScz7Ovik%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1920&quot; height=&quot;1080&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그리고 여기에 집중해봅시다. 우리는 지금 상황에서 오른쪽으로 미는 행위가 F[4], 즉 앞 4글자에서 접두사와 접미사의 최대 일치하는 부분과 관련이 있음을 알 수 있습니다. 만약 한 칸만 밀게 될 경우 F(3) &amp;ne; 3일 때에 겹치는 구간이 그대로 겹쳐집니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/7gIO3/btrIGyMI3AB/DgkFkFIniMGv4C56s16oJ1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/7gIO3/btrIGyMI3AB/DgkFkFIniMGv4C56s16oJ1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/7gIO3/btrIGyMI3AB/DgkFkFIniMGv4C56s16oJ1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F7gIO3%2FbtrIGyMI3AB%2FDgkFkFIniMGv4C56s16oJ1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1920&quot; height=&quot;1080&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;우리는 F(3) = 2라는걸 알고 있기 때문에 접두사와 접미사가 2칸 겹치도록 바로 아래의 문자열을 2칸 밀어버리면 됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bpcgp6/btrIzDINdrz/PMLcyuR2YolWOXdw79wBxK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bpcgp6/btrIzDINdrz/PMLcyuR2YolWOXdw79wBxK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bpcgp6/btrIzDINdrz/PMLcyuR2YolWOXdw79wBxK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fbpcgp6%2FbtrIzDINdrz%2FPMLcyuR2YolWOXdw79wBxK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1920&quot; height=&quot;1080&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그리고 이렇게 2칸을 밀면 마지막 글자를 제외하고 나머지 글자는 자동으로 일치한다는 사실을 잘 이해하셔야 합니다. 첫 번째와 두 번째 문자열에서 해당 부분은 S[8] = 4였기 때문에 일치하고, 두 번째와 세 번째 문자열에서 해당 부분은 F(3)을 이용해 우리가 의도적으로 값이 동일하도록 밀었기 때문에 일치합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bs3PCN/btrIyYM9U29/2jInDrxRvGj0fwOLkOsKm0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bs3PCN/btrIyYM9U29/2jInDrxRvGj0fwOLkOsKm0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bs3PCN/btrIyYM9U29/2jInDrxRvGj0fwOLkOsKm0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fbs3PCN%2FbtrIyYM9U29%2F2jInDrxRvGj0fwOLkOsKm0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1920&quot; height=&quot;1080&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;마지막 글자를 제외한 나머지 부분의 값이 동일하다는걸 알고 있기 때문에 우리는 진한 초록과 연한 초록으로 표시한 마지막 글자만 확인하면 됩니다. 이 때 진한 초록은 S[9]이고, 연한 초록은 앞 4글자에서 접두사와 접미사의 최대 일치하는 부분의 한칸 뒤인 S[F(3)] = S[2]입니다. 이 둘은 A로 동일하기 때문에 최종적으로 F(9) = 3임을 알 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cezMow/btrIyZeek6B/CZ8kKjIGH7QzhoMrDMWQOk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cezMow/btrIyZeek6B/CZ8kKjIGH7QzhoMrDMWQOk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cezMow/btrIyZeek6B/CZ8kKjIGH7QzhoMrDMWQOk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcezMow%2FbtrIyZeek6B%2FCZ8kKjIGH7QzhoMrDMWQOk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1920&quot; height=&quot;1080&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;지금까지 한 얘기를 다시 정리해보겠습니다. 기본적으로 현재의 F(i) 값을 구할 때에는 길이 F(i-1)만큼의 구간을 그대로 가져온 후 다음 한 글자가 일치하는지를 확인합니다. 만약 일치한다면 F(i) = F(i-1) + 1로 쉽게 계산됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bbp2B1/btrIA1ijfN5/ztf1dePsxPaN76YGikkwG0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bbp2B1/btrIA1ijfN5/ztf1dePsxPaN76YGikkwG0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bbp2B1/btrIA1ijfN5/ztf1dePsxPaN76YGikkwG0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fbbp2B1%2FbtrIA1ijfN5%2Fztf1dePsxPaN76YGikkwG0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1920&quot; height=&quot;1080&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;하지만 그림과 같이 일치하지 않을 경우에는 아래의 문자열을 적절하게 밀어주어야 합니다. 그리고 여기서 얼마나 밀어줄지 결정하기 위해서 현재 겹친 영역(파란색 테두리 영역)에서 접두사와 접미사가 얼마나 겹쳤는지를 참고할 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cFHHa5/btrIH5Q3I6z/Y6YX7WSR1EfKxEN9yPVGFk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cFHHa5/btrIH5Q3I6z/Y6YX7WSR1EfKxEN9yPVGFk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cFHHa5/btrIH5Q3I6z/Y6YX7WSR1EfKxEN9yPVGFk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcFHHa5%2FbtrIH5Q3I6z%2FY6YX7WSR1EfKxEN9yPVGFk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1920&quot; height=&quot;1080&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이렇게 이전에 일치하던 구간에서 접두사와 접미사가 겹치는 구간을 그대로 살려 아래의 문자열을 밀어준 후 마지막 글자를 비교하면 됩니다. 만약 여기서 각 마지막 글자가 다르다면 초록색 구간 안에서 접두사와 접미사가 얼마나 겹쳤는지를 확인해 그 구간을 그대로 살려 다시 아래의 문자열을 밀어주는걸 반복하면 됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이렇게 실패 함수에 대한 설명을 마쳤는데 아마 정말 심각하게 헷갈리고 혼란스러울 수 있습니다. 하지만 그것이 정상이니 나만 바보인건가 하고 생각할 필요는 없고, 심호흡을 크게한 뒤 잠시 맑은 공기를 마시고 다시 돌아옵시다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이제 이것을 구현하는 아주 큰 고비가 남았습니다. 구현을 할 때에는 실제로 문자열을 미는게 아니라 위와 아래에서 비교를 해야 할 두 인덱스만 가지고 갑니다. 도식화해서 보여드린 실패 함수 계산 과정을 인덱스와 함께 다시 확인해봅시다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cLBGyZ/btrIyYGonjj/LjkCMkv4A8k5jx7b1QnKW0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cLBGyZ/btrIyYGonjj/LjkCMkv4A8k5jx7b1QnKW0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cLBGyZ/btrIyYGonjj/LjkCMkv4A8k5jx7b1QnKW0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcLBGyZ%2FbtrIyYGonjj%2FLjkCMkv4A8k5jx7b1QnKW0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1920&quot; height=&quot;1080&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;먼저 i와 j를 각각 위와 아래의 인덱스라고 합시다. S[i]와 S[j]가 일치하는지를 비교하게 되는데, S[i] == S[j]일 경우 F[i] = j+1이고 i와 j를 모두 1 증가시키면 됩니다. 1-indexed, 0-indexed 등의 문제로 F(i) = j+1인지 F(i) = j인지 등이 굉장히 헷갈릴 수 있는데, F(x)의 정의가 문자열 S[0:x+1]에서 접두사와 접미사가 일치하는 최대 길이임을 다시 한 번 상기하면서 잘 이해해봅시다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/JnPHq/btrIGxNOdwz/8g0ARjj5hIskwjxKgPvDa0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/JnPHq/btrIGxNOdwz/8g0ARjj5hIskwjxKgPvDa0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/JnPHq/btrIGxNOdwz/8g0ARjj5hIskwjxKgPvDa0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FJnPHq%2FbtrIGxNOdwz%2F8g0ARjj5hIskwjxKgPvDa0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1920&quot; height=&quot;1080&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;S[i] != S[j]일 경우에는 우선 j가 F(i-1)이고 초록색 영역의 길이가 F(j-1)임을 이해해야 합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bENJOx/btrIyZyAjYt/kTQolWAn4ByMYwso2t0k1k/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bENJOx/btrIyZyAjYt/kTQolWAn4ByMYwso2t0k1k/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bENJOx/btrIyZyAjYt/kTQolWAn4ByMYwso2t0k1k/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbENJOx%2FbtrIyZyAjYt%2FkTQolWAn4ByMYwso2t0k1k%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1920&quot; height=&quot;1080&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그렇게 되면 i는 그대로이고 j만 F(j-1)로 바뀜을 알 수 있습니다. 만약 여기에서 또 S[i]와 S[j]가 일치하지 않는다면 다시 j = F(j-1)로 바뀌게 됩니다. 지금까지 제 강의들에서는 동작 원리를 설명드리고 제 코드를 보여드리기 전에 먼저 구현을 해보시라고 권유를 하는 경우가 많았지만 이번 내용은 아무리 생각해도 이 설명만을 보고 동작 원리를 완벽히 이해해서 구현을 하는게 불가능에 가깝다고 생각을 하기 때문에 코드를 바로 보여드리겠습니다. 코드를 보고 아주 긴 시간동안 머리를 쥐어뜯으며 이해를 해보려고 노력해봅시다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bWRv8T/btrItlIPfWz/Gq8iNjVdJyB00ywqYjzj20/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bWRv8T/btrItlIPfWz/Gq8iNjVdJyB00ywqYjzj20/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bWRv8T/btrItlIPfWz/Gq8iNjVdJyB00ywqYjzj20/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbWRv8T%2FbtrItlIPfWz%2FGq8iNjVdJyB00ywqYjzj20%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1920&quot; height=&quot;1080&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 실패 함수 내용이 꽤 난해했는데 코드를 보면 당혹스러울 정도로 간결합니다. 간결하지만 하나하나 뜯어보면 앞에서 설명한 내용이 다 잘 들어가있습니다. 앞에서 말했던 것 처럼 인덱스 i는 위에서 비교가 이루어지는 문자열의 위치이고 인덱스 j는 아래에서 비교가 이루어지는 문자열의 위치입니다. f[i]를 구할 때에는 당연히 s[i]를 비교하게 되고 j는 비교를 하면서 옮겨다니게 됩니다. 05번째 줄의 while문이 많이 헷갈릴텐데, 일단 s[i]와 s[j]가 일치한다면 while문 안의 조건이 false이니 바로 06번째 줄로 가서 f[i] = ++j, 즉 &lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;j += 1 /&lt;/span&gt; f[i] = j 이 실행됩니다. s[i]와 s[j]가 일치하지 않는다면 while문에서 계속 붙잡혀있으면서 j = f[j-1]으로 바꿔나가는데 이게 앞에서 같이 살펴본 것 처럼 밑의 문자열을 적절하게 밀어주는 과정인거고 그러다가 j = 0이 되면 while문을 탈출하는 로직입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cm0Zj4/btrIxv4Zu7W/fs47mIfVV0nLfxRIOTUWk1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cm0Zj4/btrIxv4Zu7W/fs47mIfVV0nLfxRIOTUWk1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cm0Zj4/btrIxv4Zu7W/fs47mIfVV0nLfxRIOTUWk1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fcm0Zj4%2FbtrIxv4Zu7W%2Ffs47mIfVV0nLfxRIOTUWk1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1920&quot; height=&quot;1080&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;드디어 KMP를 이해하기 위한 모든 준비가 끝났습니다. 실패 함수를 이해하는게 KMP 이해의 80% 이상을 차지하고 있기 때문에 실패 함수를 이해했다면 KMP는 사실상 거의 거저 따라온다고 생각하면 됩니다. 우리는 A 안에 B가 들어있는지 구하고 싶습니다. 그냥 정직하게 짜면 &lt;span&gt;제일 앞에서 본 것 처럼&lt;span&gt; &lt;/span&gt;&lt;/span&gt;O(|A| &amp;times; |B|)가 걸릴테지만 KMP 알고리즘을 통해 O(|A| + |B|)에 해결하고 싶습니다. 이 과정에서 B에 대한 실패 함수를 필요로 하는데, 실패 함수를 복습하는 차원에서 저 표를 채워봅시다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bMLyLZ/btrIyxCfvZd/nK3Qlywc29xgonNBKr0erk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bMLyLZ/btrIyxCfvZd/nK3Qlywc29xgonNBKr0erk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bMLyLZ/btrIyxCfvZd/nK3Qlywc29xgonNBKr0erk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbMLyLZ%2FbtrIyxCfvZd%2FnK3Qlywc29xgonNBKr0erk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1920&quot; height=&quot;1080&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;표를 채우면서 실패 함수 과정을 잘 따라가보셨을거라고 생각합니다. 그리고 신기하게도 A에서 B를 찾는 KMP 자체가 실패 함수를 찾는 과정과 굉장히 유사합니다. 과정을 같이 확인해봅시다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/y91Qg/btrIynSVvt0/apzsSagFoI7jf10h0lO2L0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/y91Qg/btrIynSVvt0/apzsSagFoI7jf10h0lO2L0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/y91Qg/btrIynSVvt0/apzsSagFoI7jf10h0lO2L0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fy91Qg%2FbtrIynSVvt0%2FapzsSagFoI7jf10h0lO2L0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1920&quot; height=&quot;1080&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;또 다시 i, j가 나옵니다. 이 i, j는 실패 함수와 같이 위(=A)와 아래(=B)에서 비교가 이루어지는 문자의 위치를 말합니다. 일단 처음엔 A[0]과 B[0]을 비교하고 둘은 일치합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cjHNpu/btrIADueEIk/SWs9kGL3bCKSmFnbU5UuPK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cjHNpu/btrIADueEIk/SWs9kGL3bCKSmFnbU5UuPK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cjHNpu/btrIADueEIk/SWs9kGL3bCKSmFnbU5UuPK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcjHNpu%2FbtrIADueEIk%2FSWs9kGL3bCKSmFnbU5UuPK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1920&quot; height=&quot;1080&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;일치하니까 계속 가봅시다. 일단 당장은 왜 그런지 이유를 생각하지 마시고 그냥 설명을 따라와주세요. 실패 함수를 구할 때와 마찬가지라고 생각할 수 있는데, 밑의 문자열을 움직이지 말고 i와 j를 둘 다 1 늘려서 일치하는지 확인합니다. A[1]과 B[1]이 일치합니다. 이제 계속 일치하는 부분은 한번에 쭉 보여드리겠습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/buSfrt/btrIzaZ7Cgu/u3nVwVrybsbHMLuoFoAtkK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/buSfrt/btrIzaZ7Cgu/u3nVwVrybsbHMLuoFoAtkK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/buSfrt/btrIzaZ7Cgu/u3nVwVrybsbHMLuoFoAtkK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbuSfrt%2FbtrIzaZ7Cgu%2Fu3nVwVrybsbHMLuoFoAtkK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1920&quot; height=&quot;1080&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dMzF2u/btrIBU4iUlO/KRykh3PyXFxpoz21nltQJk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dMzF2u/btrIBU4iUlO/KRykh3PyXFxpoz21nltQJk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dMzF2u/btrIBU4iUlO/KRykh3PyXFxpoz21nltQJk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdMzF2u%2FbtrIBU4iUlO%2FKRykh3PyXFxpoz21nltQJk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1920&quot; height=&quot;1080&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dcArOp/btrIEYdSGEp/M0rQmSH9D2wn9qkn3dkk8K/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dcArOp/btrIEYdSGEp/M0rQmSH9D2wn9qkn3dkk8K/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dcArOp/btrIEYdSGEp/M0rQmSH9D2wn9qkn3dkk8K/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdcArOp%2FbtrIEYdSGEp%2FM0rQmSH9D2wn9qkn3dkk8K%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1920&quot; height=&quot;1080&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bukJlF/btrIH7nN6Kx/dUK5zB43lw4w9b7ZVm8PTk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bukJlF/btrIH7nN6Kx/dUK5zB43lw4w9b7ZVm8PTk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bukJlF/btrIH7nN6Kx/dUK5zB43lw4w9b7ZVm8PTk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbukJlF%2FbtrIH7nN6Kx%2FdUK5zB43lw4w9b7ZVm8PTk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1920&quot; height=&quot;1080&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;잘 나가다가 i = 5, j = 5에서 두 글자의 불일치가 발생했습니다. 그러면 아래의 문자열을 옮겨야하는데 여기서 한 칸만 옮기면 기존의 비효율적인 방법과 다를게 없습니다. 여기서 아래의 문자열을 얼마만큼 오른쪽으로 옮기면 될지, 다른 말로 표현하면 j의 값을 얼마로 두면 될지 실패 함수를 구할 때 나왔던 비슷한 상황을 떠올리면서 알아맞춰봅시다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/nT1b7/btrIEYSscH8/hemNgneZNw5sOO3VdUMXtK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/nT1b7/btrIEYSscH8/hemNgneZNw5sOO3VdUMXtK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/nT1b7/btrIEYSscH8/hemNgneZNw5sOO3VdUMXtK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FnT1b7%2FbtrIEYSscH8%2FhemNgneZNw5sOO3VdUMXtK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1920&quot; height=&quot;1080&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;저기 실패 함수의 값 중 하나에 주황색으로 칠을 해두었습니다. 저 F(4) = 3라는 값은 &quot;ABABA&quot;에서 접두사와 접미사가 일치하는 최대 길이가 3글자라는 의미입니다. 이제 뭔가 좀 보이시나요?&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/4Rcy1/btrIvpjLMlV/taLAwro4sOcAytirdQ7kz0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/4Rcy1/btrIvpjLMlV/taLAwro4sOcAytirdQ7kz0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/4Rcy1/btrIvpjLMlV/taLAwro4sOcAytirdQ7kz0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F4Rcy1%2FbtrIvpjLMlV%2FtaLAwro4sOcAytirdQ7kz0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1920&quot; height=&quot;1080&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;잠깐 문자열 A는 신경쓰지 말고 원래의 B와 실패 함수를 이용해 옮긴 B에만 집중을 해보겠습니다. 이전에 실패 함수에서 본 것과 같은 맥락인데 비록 지금 B[i]와 B[j]가 다르기 때문에 B를 옮겨야하지만 앞의 다른 글자들은 다 일치했으니 일치하는 구간을 최대한 살리고 싶습니다. 그렇기 때문에 &quot;ABABA&quot;에서 접미사와 접두사가 일치하는 3글자를 그대로 살리면서 아래의 문자열을 이동시키면 됩니다. 그런데 이 때 j의 값은 얼마일까요? 물론 눈으로 보면 3이란걸 알 수 있긴한데 이 3이라는 값은 어떻게 계산된 값일까요?&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/n4gB8/btrIBUQNEW6/OL7ECBccfwK9beKGkB2sf0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/n4gB8/btrIBUQNEW6/OL7ECBccfwK9beKGkB2sf0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/n4gB8/btrIBUQNEW6/OL7ECBccfwK9beKGkB2sf0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fn4gB8%2FbtrIBUQNEW6%2FOL7ECBccfwK9beKGkB2sf0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1920&quot; height=&quot;1080&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 값은 F(j-1) = F(4)입니다. F(4)의 정의가 &quot;ABABA&quot;에서 접두사와 접미사가 일치하는 최대 길이였고, 우리는 일치하는 &quot;ABA&quot;의 다음 글자를 B[i]와 비교해야 하기 때문에 그렇습니다. 0-indexed, 1-indexed 등의 문제로 F(4)인지 F(4)+1인지 이런게 헷갈린다면 F의 정의나 앞에서 그림을&amp;nbsp; 참고해서 확실히 바로 잡고 가는걸 추천드립니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/yqisH/btrIvpDZj8T/aB2IZYLcK1XdWLbQqQeiVk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/yqisH/btrIvpDZj8T/aB2IZYLcK1XdWLbQqQeiVk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/yqisH/btrIvpDZj8T/aB2IZYLcK1XdWLbQqQeiVk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FyqisH%2FbtrIvpDZj8T%2FaB2IZYLcK1XdWLbQqQeiVk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1920&quot; height=&quot;1080&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그렇기 때문에 결론적으로 우리는 A[i]와 B[j]의 불일치가 발생하면 j를 F[j-1]로 옮기면 됩니다. 실패 함수를 구할 때 하던 방식과 동일합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bMOOfL/btrIzE8KssH/Zy8qNVi6DENh7GkcXN4Ds0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bMOOfL/btrIzE8KssH/Zy8qNVi6DENh7GkcXN4Ds0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bMOOfL/btrIzE8KssH/Zy8qNVi6DENh7GkcXN4Ds0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbMOOfL%2FbtrIzE8KssH%2FZy8qNVi6DENh7GkcXN4Ds0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1920&quot; height=&quot;1080&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그리고 그 다음 비교를 이어가면 됩니다. A[5]과 B[3]이 일치합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/Crfw6/btrIxUjaRJ0/CVvZrXmG0hRqbJStkStYek/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/Crfw6/btrIxUjaRJ0/CVvZrXmG0hRqbJStkStYek/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/Crfw6/btrIxUjaRJ0/CVvZrXmG0hRqbJStkStYek/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FCrfw6%2FbtrIxUjaRJ0%2FCVvZrXmG0hRqbJStkStYek%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1920&quot; height=&quot;1080&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;i, j를 모두 1 증가시킵니다. A[6]과 B[4]가 일치합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/w8HT3/btrIzEnmxWP/QA1UMeJH2yU6xN5RSMkcq0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/w8HT3/btrIzEnmxWP/QA1UMeJH2yU6xN5RSMkcq0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/w8HT3/btrIzEnmxWP/QA1UMeJH2yU6xN5RSMkcq0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fw8HT3%2FbtrIzEnmxWP%2FQA1UMeJH2yU6xN5RSMkcq0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1920&quot; height=&quot;1080&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;i, j를 모두 1 증가시킵니다. 이번에는 A[7]과 B[5]가 일치하지 않습니다. j를 어떻게 옮겨야할지 알아맞춰봅시다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/TFR3E/btrIH7BlblM/dffRpTGkZOduf5Kfgn6kU1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/TFR3E/btrIH7BlblM/dffRpTGkZOduf5Kfgn6kU1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/TFR3E/btrIH7BlblM/dffRpTGkZOduf5Kfgn6kU1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FTFR3E%2FbtrIH7BlblM%2FdffRpTGkZOduf5Kfgn6kU1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1920&quot; height=&quot;1080&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;첫 5글자에서 접미사와 접두사가 일치하는 최대 길이인 F(4)로 옮기면 됩니다. F(4)가 3이니 3개가 겹치는건 그대로 활용할 수 있고 A[i]와 B[j]를 비교해볼 차례입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/OZJwG/btrIBVa3PzM/GsjJdM9r1zajKr5d8Fj6Wk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/OZJwG/btrIBVa3PzM/GsjJdM9r1zajKr5d8Fj6Wk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/OZJwG/btrIBVa3PzM/GsjJdM9r1zajKr5d8Fj6Wk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FOZJwG%2FbtrIBVa3PzM%2FGsjJdM9r1zajKr5d8Fj6Wk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1920&quot; height=&quot;1080&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;아쉽게도 글자가 일치하지 않습니다. 이러면 또 다시 j를 옮겨야하는데 어디로 옮겨야할까요?&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/U9GmB/btrIFIV3Ezv/WWoZlX6OI2JmI6ArXj0Iz1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/U9GmB/btrIFIV3Ezv/WWoZlX6OI2JmI6ArXj0Iz1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/U9GmB/btrIFIV3Ezv/WWoZlX6OI2JmI6ArXj0Iz1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FU9GmB%2FbtrIFIV3Ezv%2FWWoZlX6OI2JmI6ArXj0Iz1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1920&quot; height=&quot;1080&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;첫 3글자에서 접미사와 접두사가 일치하는 최대 길이인 F(2)로 옮기면 됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bUAe9r/btrIEXMK8vh/hxN2VmmzAoGGBfEKKaboP1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bUAe9r/btrIEXMK8vh/hxN2VmmzAoGGBfEKKaboP1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bUAe9r/btrIEXMK8vh/hxN2VmmzAoGGBfEKKaboP1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbUAe9r%2FbtrIEXMK8vh%2FhxN2VmmzAoGGBfEKKaboP1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1920&quot; height=&quot;1080&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;하지만 이번에도 다음 글자가 일치하지 않았습니다. j를 다시 옮겨야 합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/ZKhGL/btrIzaeKUgz/YNJ8QsPwpzEwWKUWxRpUZ0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/ZKhGL/btrIzaeKUgz/YNJ8QsPwpzEwWKUWxRpUZ0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/ZKhGL/btrIzaeKUgz/YNJ8QsPwpzEwWKUWxRpUZ0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FZKhGL%2FbtrIzaeKUgz%2FYNJ8QsPwpzEwWKUWxRpUZ0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1920&quot; height=&quot;1080&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;j를 F(0)으로 옮기면 됩니다. 이제 다시 바닥에서 시작하는 느낌이네요. 그리고 여기서마저 글자가 일치하지 않습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/sdrwN/btrIBTqMjo3/TSkPduF7THLEXvoIOBUibK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/sdrwN/btrIBTqMjo3/TSkPduF7THLEXvoIOBUibK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/sdrwN/btrIBTqMjo3/TSkPduF7THLEXvoIOBUibK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FsdrwN%2FbtrIBTqMjo3%2FTSkPduF7THLEXvoIOBUibK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1920&quot; height=&quot;1080&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;더 이상 j를 옮길 곳이 없으니 i를 1 증가시킵니다. 이번에는 A[i]와 B[j]가 일치하네요. 계속 하던대로 i와 j를 모두 1 증가시킵니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bgXpx0/btrIEcQWFTd/BHhLmZGhNoX884ELBhB3U0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bgXpx0/btrIEcQWFTd/BHhLmZGhNoX884ELBhB3U0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bgXpx0/btrIEcQWFTd/BHhLmZGhNoX884ELBhB3U0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbgXpx0%2FbtrIEcQWFTd%2FBHhLmZGhNoX884ELBhB3U0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1920&quot; height=&quot;1080&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이번에도 일치합니다. 계속 쭉 일치하기 때문에 조금 생략을 하고 넘어가겠습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/XjURk/btrIGylE54w/bMapZJwoKAszEKIQKFpkSK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/XjURk/btrIGylE54w/bMapZJwoKAszEKIQKFpkSK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/XjURk/btrIGylE54w/bMapZJwoKAszEKIQKFpkSK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FXjURk%2FbtrIGylE54w%2FbMapZJwoKAszEKIQKFpkSK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1920&quot; height=&quot;1080&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이렇게 j가 8, 즉 끝에 도달하게 되면 A 안에 B가 있음을 확인할 수 있습니다. 만약 A 안에 B가 있는지 여부만을 확인하고 싶다면 여기서 탐색을 중단하면 되지만 B가 등장하는 횟수를 구하고 싶다거나, B가 등장하는 모든 위치를 구하고 싶다면 여기서 탐색을 계속 이어나가야 합니다. 그러면 이 때 j를 어떤 값으로 바꾸면 될지 고민해봅시다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/brXA6f/btrIEb5As13/FOsh6KDpMcKr2R2fhRnHG1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/brXA6f/btrIEb5As13/FOsh6KDpMcKr2R2fhRnHG1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/brXA6f/btrIEb5As13/FOsh6KDpMcKr2R2fhRnHG1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbrXA6f%2FbtrIEb5As13%2FFOsh6KDpMcKr2R2fhRnHG1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1920&quot; height=&quot;1080&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;F(8)의 값을 참고해서 j를 3으로 옮기면 됩니다. 이후 A[i]와 B[j]를 비교한 후 다시 j를 옮기는 작업이 반복됩니다. 뒤의 작업은 생략하겠습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이렇게 KMP 알고리즘의 전 과정을 알아보았습니다. KMP에서는 접미사와 접두사의 일치를 바탕으로 탐색을 효율적으로 수행합니다. 앞에서 본 실패 함수의 코드를 잘 이용해 구현을 직접 해보셔도 좋고, 아직 자신이 없으면 바로 코드를 확인하셔도 좋습니다. 구현을 해본 후에는 &lt;a href=&quot;https://www.acmicpc.net/problem/16916&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;BOJ 16916번: 부분 문자열&lt;/a&gt; 문제에서 제대로 구현을 했는지 확인할 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/t2q4k/btrIEXlIM14/YPnwWE9QplOKNjkTezsvuK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/t2q4k/btrIEXlIM14/YPnwWE9QplOKNjkTezsvuK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/t2q4k/btrIEXlIM14/YPnwWE9QplOKNjkTezsvuK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Ft2q4k%2FbtrIEXlIM14%2FYPnwWE9QplOKNjkTezsvuK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1920&quot; height=&quot;1080&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;실패 함수 부분은 그대로 가져왔습니다. 그리고 21번째 줄부터 시작하는 for문 안에서 i와 j의 움직임을 처리하는데 실패 함수에서 보던 로직과 굉장히 유사함을 확인할 수 있습니다. 만약 24번째 줄과 같이 j가 p.size()에 도달하면 문자열 s 안에 문자열 p가 있음을 확인할 수 있는데, 이 문제에서는 부분 문자열 여부만을 판단하기에 여기서 바로 1을 출력하고 종료했습니다. 만약 탐색을 계속 이어가고자 할 경우에는 이 부분이 어떻게 바뀌어야 하는지 고민을 해보시는 것을 추천드립니다. 당장 문제집에 있는 문제 중 이런 고민이 필요한 문제가 있습니다. 그리고 정답을 받은 후 다른 분들의 코드를 보시면 알겠지만 사실 채점 서버 기준(=g++ 기준) strstr 함수가 선형 시간에 동작하기 때문에 지금처럼 그냥 단순하게 등장 여부만을 선형 시간에 확인해야할 경우에는 그냥 strstr 함수를 써서 날로 먹을 수 있긴 합니다. 하지만 등장하는 횟수를 구해야 한다거나, 아예 실패 함수를 가지고 뭔가 응용이 들어가면 단순히 strstr함수로는 해결이 힘들고 KMP가 필요하게 됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/b3Wd0l/btrIy9NEXny/4UQTk5oVagO4ubxHzUT220/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/b3Wd0l/btrIy9NEXny/4UQTk5oVagO4ubxHzUT220/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/b3Wd0l/btrIy9NEXny/4UQTk5oVagO4ubxHzUT220/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fb3Wd0l%2FbtrIy9NEXny%2F4UQTk5oVagO4ubxHzUT220%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1920&quot; height=&quot;1080&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이렇게 KMP 알고리즘을 알아보았습니다. 많이 어려운 내용이고 특히 이 알고리즘을 이번에 처음 접했을 경우 이해가 잘 가지 않는 것이 정상입니다. 이해를 위해 다른 사람들의 자료를 찾아보셔도 괜찮은데, F나 문자열의 인덱스 등이 제 강의에서 정의한 것과 다를 수 있기 때문에 이를 유의할 필요가 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;KMP는 코딩테스트 기준 그렇게까지 비중이 있는 내용은 아니기 때문에 도저히 이해가 안간다면 여기에 온 시간을 쏟기 보다는 다른 단원의 내용을 학습하는게 더 의미있을 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;한편 KMP에는 실패 함수를 이용하거나 기타 등등 다양한 응용법이 존재합니다. 해당 문제들을 응용 문제로 두긴 했지만 난이도가 꽤 높기 때문에 대회를 노리는게 아니라면 굳이 학습할 필요는 없어 보입니다. 그러면 고생 많으셨습니다.&lt;/p&gt;</description>
      <category>강좌/실전 알고리즘</category>
      <author>BaaaaaaaaaaaaaaaaaaaaaaarkingDog</author>
      <guid isPermaLink="true">https://baaaaaaaaaaaaaaaaaaaaaaarkingdog.tistory.com/1040</guid>
      <comments>https://baaaaaaaaaaaaaaaaaaaaaaarkingdog.tistory.com/1040#entry1040comment</comments>
      <pubDate>Tue, 2 Aug 2022 00:44:14 +0900</pubDate>
    </item>
    <item>
      <title>WACon 2022 출제(&amp;amp;운영?) 후기</title>
      <link>https://baaaaaaaaaaaaaaaaaaaaaaarkingdog.tistory.com/1058</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;WACon에 출제를 하게 되었습니다. 어떻게 하다가 이런 대회가 열리게 된건지 잘 모르겠긴 하지만 새로운 대회는 언제나 환영이죠 :p 사실 원래는 본선때 해킹대회 출제 브이로그를 찍어보겠다고 영상을 이것저것 찍었는데, 찍던 중간에 저는 이런걸 할 수 없는 성격이란걸 깨달아버렸습니다. 브이로그 유튜버분들 존경합니다,,,&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;사실 제일 처음 출제를 해본 CTF는 코드게이트 2022였지만 코드게이트 2022는 사실상 문제만 만들면 됐고 그 뒤의 세팅은 저와 무관한 일이라는 느낌이었다면 WACon은 아예 제가 속해있는 CTF팀에서 운영을 맡았다보니 운영을 근거리에서 지켜볼 수 있었다는 차이가 있었습니다. 물론 저는 아직 도커와도 친숙하지 않고 또 아예 CTFd를 만져본게 처음이라 &lt;span&gt;전반적으로 서버랑 도커&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;관리를 다른 팀원분들, 특히 sqrtrev님이랑 GoRiyA님이 도맡아서 해주셨고 저는 그냥 문제 정보 등록 같은 노가다나 조금 거들었지만 아무튼 이렇게 한 번 경험해본게 좋았습니다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;문제 아이디어가 엥간치 있었어서 이번에 거의 문제공장장 느낌으로 easy, medium 수준의 문제를 여럿 찍어냈습니다. 예선에 The Game of DES, Zero time signature, Type confusion, Hashashashashash를, 본선에 BYOS, mistake, draclean, mosaic, Sudoku game을 냈습니다. 암호학이랑 misc 분야는 익숙했지만 어쩌다보니 리버싱 문제도 예선과 본선에 1개씩 내게 됐네요.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;사실 요즘 고등학생들의 수준을 잘 몰라서 본의아니게 예선때에는 주니어부에 대한 배려가 조금 부족했던 것 같습니다. 소오오오오올직히 The Game of DES는 점수를 퍼다주는 문제였고 실제로 일반부에서는 그냥 점수 자판기였는데 주니어부에서 딱 2팀만 풀어낸걸 보고 조금 아쉽긴 했습니다. Type confusion도 주니어에서 한 팀은 풀 줄 알았는데ㅠ... 그래서 본선에서는 분야별로 한 문제씩은 저희 나름대로 쉬운 문제를 두었는데 (pwn - old style, crypto - mistake, misc - ide, rev - draclean, web - BabyJS) 딴건 다 솔버가 나왔지만 draclean은 안풀렸네요. ㅈㅅ... 덜 꼬아낼걸 그랬습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Sudoku game의 경우, 혼자 떠올린 게임이었고 저는 그냥 정직하게 백트래킹으로 AI를 만들었습니다. 나름 AI를 열심히 짠다고는 짰는데 플레이어가 그냥 매 순간마다 가능한 칸 중에서 랜덤으로 두더라도 승률 30% 정도는 나오길래 어쩔 수 없이 연결 횟수를 팀 당 1회로 제한하고 sleep도 무지막지하게 두었습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 때 팀 당 1회 제한을 어떻게 해야하나 고민을 했는데 diff님이 filelock을 알려주셔서 유용하게 써먹었습니다. 저는 처음에 CTFd 안에 팀별로 고유한 팀 토큰이 있다고 생각해서 그냥 그걸 토큰으로 사용하려고 했으나 확인했더니 그렇지가 않아서 대회장에서 급하게 토큰을 만들었습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1080&quot; data-origin-height=&quot;1440&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bBxZGp/btrH3Q1lgPr/CkK6M8ZkLzDwfyia2nkI10/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bBxZGp/btrH3Q1lgPr/CkK6M8ZkLzDwfyia2nkI10/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bBxZGp/btrH3Q1lgPr/CkK6M8ZkLzDwfyia2nkI10/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbBxZGp%2FbtrH3Q1lgPr%2FCkK6M8ZkLzDwfyia2nkI10%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1080&quot; height=&quot;1440&quot; data-origin-width=&quot;1080&quot; data-origin-height=&quot;1440&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;혹시 filelock에서 취약점이 있지는 않을까 노심초사했는데 다행히 그렇지는 않았네요. 다만 간혹 연결이 비정상적으로 종료된 후 접속이 계속 안되는 경우가 있어서 처음에는 어떻게 해결해야하나 애를 좀 먹었는데 도커 안에 들어가서 그냥 파일을 지우면 되는걸 확인해서 그 뒤로는 요청이 들어와도 큰 어려움 없이 처리를 할 수 있었습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;사실 이렇게 sleep을 두고 접속을 1회로 제한해도 그냥 승률 30%짜리로 계속 돌리면서 +12점이 되길 기도하는 식으로 했을 때 &lt;span&gt;운이 좋으면&lt;span&gt; 플래그를 얻을 수 있긴 했는데 더 sleep을 늘리긴 그래서 어쩔 수 없이 이정도로 했습니다. 참고로 시뮬레이션을 했을 때 승률 30%로는 평균적으로 60-80시간이 지나면 +12점을 얻을 수 있고, 50%로는 20분이 지나면 +12점에 도달할 수 있었습니다. &lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span&gt;그래서 제 AI랑 승률이 반반만 나와도 플래그를 획득할 수 있게 했는데 필승전략이 있는줄은 몰랐습니다,,,,&amp;nbsp; (&lt;a href=&quot;https://mathoverflow.net/questions/297872/who-wins-two-player-sudoku&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;여기&lt;/a&gt; 참고) &lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span&gt;전략을 직접 떠올린 팀도 있었고 열심히 검색해 저 글을 찾은 팀도 있었습니다. 저도 출제 당시 나름대로 혹시 기존에 있는 게임은 아닐까 걱정하면서 열심히 찾았지만 저런 글을 못찾았는데 아쉽네요ㅜ 그래도 검색으로 풀 수 있었던건 아쉬운 점이었지만, 필승전략이 있었기 때문에 노잼 백트래킹 빡구현문제가 예스잼 게임이론문제가 된 것 같습니다.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;출제 당시에는 풀이까지 상세하게 작성할만큼 여유가 없었고 익스플로잇 코드만 다 작성했었습니다. 짬날때마다 제가 출제한 문제들에 대한 풀이는 틈틈히 작성을 하고 있긴 한데 언제 정리를 다 해서 공개를 할 수 있을지는 모르겠습니다. 아마 여러 일 중에서 우선순위가 굉장히 낮을 것 같네요ㅠ 그래도 제가 낸 문제 중에 풀이가 궁금한게 있으면 언제든 편하게 질문주세요.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이거 대회때문에 계속 서울 왔다갔다하고 진행중에는 잠도 잘 못자고 되게 정신없었는데 끝나니까 살 것 같네요. 그래도 제가 낸 문제들을 정말 뛰어난 분들이 도전해주시는게 참 흔치않은 기회인데 감사한 일이었습니다. 또 주니어부 분들이 제 문제를 통해 뭔가 얻어갈 수 있다면 기쁠 것 같습니다. 특히 mistake와 Type confusion은 복습해볼 가치가 있지 않나 생각하긴 합니다.&lt;/p&gt;</description>
      <category>대회/각종 대회 후기</category>
      <author>BaaaaaaaaaaaaaaaaaaaaaaarkingDog</author>
      <guid isPermaLink="true">https://baaaaaaaaaaaaaaaaaaaaaaarkingdog.tistory.com/1058</guid>
      <comments>https://baaaaaaaaaaaaaaaaaaaaaaarkingdog.tistory.com/1058#entry1058comment</comments>
      <pubDate>Sat, 23 Jul 2022 11:34:17 +0900</pubDate>
    </item>
    <item>
      <title>버그바운티 대회가 있다고 합니다</title>
      <link>https://baaaaaaaaaaaaaaaaaaaaaaarkingdog.tistory.com/1056</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;https://www.boannews.com/media/view.asp?idx=108139&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;저는 이런거에 사실상 노베이스라 딱히 할 수 있는게 없지만, 대충 찾아보니 타겟 기업들이 중소기업들인 것 같던데 잘은 몰라도 아마 엄청 견고하지는 않을 것 같기도 하고 그렇네요..!&lt;/p&gt;</description>
      <category>컴퓨터과학/ETC</category>
      <author>BaaaaaaaaaaaaaaaaaaaaaaarkingDog</author>
      <guid isPermaLink="true">https://baaaaaaaaaaaaaaaaaaaaaaarkingdog.tistory.com/1056</guid>
      <comments>https://baaaaaaaaaaaaaaaaaaaaaaarkingdog.tistory.com/1056#entry1056comment</comments>
      <pubDate>Tue, 19 Jul 2022 15:10:31 +0900</pubDate>
    </item>
    <item>
      <title>22 현대모비스 알고리즘 경진대회 후기</title>
      <link>https://baaaaaaaaaaaaaaaaaaaaaaarkingdog.tistory.com/1055</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;오랜만에 프로그래밍 대회에 참여했습니다. 갑자기 ps가 그리워졌다기 보다는&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;886&quot; data-origin-height=&quot;838&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bhB332/btrG0Beiy76/973KhHoATLmAN6fPl2a9K1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bhB332/btrG0Beiy76/973KhHoATLmAN6fPl2a9K1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bhB332/btrG0Beiy76/973KhHoATLmAN6fPl2a9K1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbhB332%2FbtrG0Beiy76%2F973KhHoATLmAN6fPl2a9K1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;886&quot; height=&quot;838&quot; data-origin-width=&quot;886&quot; data-origin-height=&quot;838&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;상금에 눈이 돌아갔다고 해도 될지도...? 그래도 한동안 안하다가 다시 하니까 재밌긴 했습니다. 아무리 ps에 손을 뗀지 오래됐다고 해도 설마 50등 안에 못들기야 하겠나 하는 생각이 있긴 했지만 사실 작년 대회에서는 50등 안에 못들긴 했습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;예선은 그냥 뭐 그냥저냥 1-4 맞추고 5번 O(2^N)으로 돌렸더니 무려 12등에 안착했고 본선은 1, 2 풀고 3, 4는 도저히 문제가 무슨 뜻인지를 이해할수가 없어서 대충 NO랑 0 출력해서 점수 긁었더니 각각 150점과 24점을 받으며 22등을 기록해서 아이패드 Air를 받을 것 같습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;애초에 3등 안쪽은 기대도 안했기 때문에 패드 정도면 만족하겠다 싶었긴 했는데 달달합니다 77ㅓㅓㅓㅓㅓ억&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;패드 받았다고 자랑하려고 쓴 후기는 아니고, 참가자 입장에서 대회에 관해 마음에 들지 않는 것이 너무 많아 투덜거림을 포함한 후기를 작성하려고 합니다. 불만을 크게 3가지로 나눠서 쓸 수 있는데,&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1. 알고리즘 대회에 대한 이해가 부족한 것으로 보이는 대회 환경&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2022년의 알고리즘 대회라고 하면 채점 결과에 대한 피드백 제공(최소 코포처럼 pretest일지라도), 명확한 시간 제한/메모리 제한 조건 안내 등은 숨쉬듯이 자연스럽게 따라오는 환경이라고 생각하는데 이번 대회는 그러지 않았습니다. 다른 무엇보다 예선 3번 문제에서 제가 생각한 풀이가 메모리를 많이 사용할 것으로 보여 메모리 제한이 어떻게 되는지 물어봤는데 알려주지 않는다는 답변을 받고 정말 황당했습니다. 또 저는 재귀를 쓰지 않아 상관이 없었지만 스택메모리에 대한 안내가 없었던 것도 문제였습니다. 작년에 똑같이 구름에서 진행됐던 스코페에서도 스택메모리 관련 이슈로 난리가 났었는데 달라진게 없네요,,&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2. 참가자에게 불편한 감정을 불러일으키는 규칙&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;예선에 적용되었던 IDE 사용 금지, 복사 붙여넣기 금지 조건이 많이 불편했고, 본선에서는 무려 3시간 반동안 이석을 허용하지 않았습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;3. 문제 디스크립션 퀄리티&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;예선의 5문제는 괜찮았지만 본선에서 3, 4번은 서술이 너무 난해해서 아직까지도 풀이는 커녕 문제 자체를 이해하지 못하고 있습니다. 끝나고 사람들 얘기를 들어보니 저만 겪었던 문제는 아닌 것 같네요.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;불만을 길게 얘기하긴 했는데 그렇다고 해서 대회에 대해 부정적인 감정만 있는건 아닙니다. 우선 본선진출자에게 보내준 과일선물세트는 전혀 상상도 못했는데 정말 좋았습니다. 주말에 가족과 야무지게 뚝딱했습니다. 또 이런 대회 하나하나가 다 ps 분야에 사람들이 관심을 가지게 만드는 좋은 계기가 될 수 있다는 점에서 큰 예산과 인력을 투입해 대회를 열어준 현대모비스측에 큰 감사를 표하고 싶습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다만 좋은 의도로 연 대회가 위에서 언급한 여러가지 사소한 문제들이 겹쳐져 참가자들에게 자칫 오히려 부정적인 인식을 줄 수 있다는게 약간 아쉬울 뿐입니다. 하지만 어느새 8회가 된 SCPC도 &lt;a href=&quot;https://www.acmicpc.net/board/view/8213&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;처음&lt;/a&gt;에는 갈팡질팡한 적이 있었고, 작년에 열렸던 스코페는 아예 정해가 틀려버리는 대참사가 발생하며 폭망했었던걸 생각하면 그럴수도 있다 싶기도 하고.. 혹시 내년에도 열린다면 올해 대회에서 제기됐던 여러 문제들을 고려해주면 좋겠습니다. 전년도 1, 2, 3등 수상자에게 자문을 구하는 것도 괜찮을 것 같네요.&lt;/p&gt;</description>
      <category>대회/각종 대회 후기</category>
      <author>BaaaaaaaaaaaaaaaaaaaaaaarkingDog</author>
      <guid isPermaLink="true">https://baaaaaaaaaaaaaaaaaaaaaaarkingdog.tistory.com/1055</guid>
      <comments>https://baaaaaaaaaaaaaaaaaaaaaaarkingdog.tistory.com/1055#entry1055comment</comments>
      <pubDate>Mon, 11 Jul 2022 15:39:35 +0900</pubDate>
    </item>
    <item>
      <title>WACON 참가하세요</title>
      <link>https://baaaaaaaaaaaaaaaaaaaaaaarkingdog.tistory.com/1054</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://wacon.world/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://wacon.world/&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;제가 속한 해킹팀(Super Guesser)에서 출제를 담당했습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;대회는 6/25 오전 9시 - 6/26 오후 9시 KST이고 참가신청을 &lt;b&gt;6/23 17시까지&lt;/b&gt; 메일로 해야합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;일단 딴것보다 상금이 많이 달달하니 zl젼햌커 여러분들의 많은 참여 부탁드립니다,,,!!&lt;/p&gt;</description>
      <category>컴퓨터과학/ETC</category>
      <author>BaaaaaaaaaaaaaaaaaaaaaaarkingDog</author>
      <guid isPermaLink="true">https://baaaaaaaaaaaaaaaaaaaaaaarkingdog.tistory.com/1054</guid>
      <comments>https://baaaaaaaaaaaaaaaaaaaaaaarkingdog.tistory.com/1054#entry1054comment</comments>
      <pubDate>Sat, 4 Jun 2022 00:00:40 +0900</pubDate>
    </item>
    <item>
      <title>근로소득이 없는 프리랜서(혹은 대학생/대학원생 부업) 세금 문제</title>
      <link>https://baaaaaaaaaaaaaaaaaaaaaaarkingdog.tistory.com/1053</link>
      <description>&lt;p&gt;옛날에 혼자 정리해서 블로그에 비공개글로 써놓고 틈틈히 참고했었는데(&lt;a href=&quot;https://phdkim.net/board/free/10380/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;이 글&lt;/a&gt;도 제가 쓴 글 ㅎㅅㅎ) 최근에 또 확인해야할게 있어서 아예 공개글로 다시 정리를 했습니다. 비슷한 상황에 처해있는 분이 그리 많지는 않을 것 같지만 누군가에겐 도움이 됐으면 합니다,,, 저는 세법쪽에 아는 바가 거의 없고 열심히 검색으로 찾은 내용을 어찌저찌 재구성한거라 혹시 틀린 내용이 있다면 정정 부탁드립니다.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;b&gt;&amp;lt;사업소득&amp;gt;&lt;/b&gt; &lt;br /&gt;1.&amp;nbsp;실제&amp;nbsp;회사가&amp;nbsp;개인&amp;nbsp;A에게&amp;nbsp;사업소득&amp;nbsp;1000만원을&amp;nbsp;지급한다고&amp;nbsp;하면&amp;nbsp;3.3%를&amp;nbsp;원천징수(미리&amp;nbsp;국가에&amp;nbsp;납부)한&amp;nbsp;후&amp;nbsp;지급해야&amp;nbsp;합니다.&amp;nbsp;이&amp;nbsp;때&amp;nbsp;주의해야할건&amp;nbsp;원천징수는&amp;nbsp;실제&amp;nbsp;납부해야&amp;nbsp;하는&amp;nbsp;세금이&amp;nbsp;아닙니다.&amp;nbsp;실제&amp;nbsp;납부해야&amp;nbsp;하는&amp;nbsp;세금을&amp;nbsp;다음해&amp;nbsp;5월&amp;nbsp;종합소득세&amp;nbsp;신고&amp;nbsp;기간에&amp;nbsp;계산해서&amp;nbsp;개인에게&amp;nbsp;청구하기&amp;nbsp;전에&amp;nbsp;나라가&amp;nbsp;미리&amp;nbsp;어림잡아서&amp;nbsp;회수해가는&amp;nbsp;개념입니다.&amp;nbsp;그렇기&amp;nbsp;때문에&amp;nbsp;사실&amp;nbsp;원천징수하는&amp;nbsp;3.3%는&amp;nbsp;크게&amp;nbsp;의미가&amp;nbsp;없고&amp;nbsp;실제&amp;nbsp;개인이&amp;nbsp;부담해야&amp;nbsp;하는&amp;nbsp;세금이&amp;nbsp;얼마인지가&amp;nbsp;중요합니다. &lt;br /&gt;&lt;br /&gt;2. 실제 개인이 부담해야 하는 세금은 (2021년 기준) 총 소득이 1200만원 이하일 경우 6%, 4600만원 이하일 경우 1200만원까지는 6%이고 그 이후는 15%, ... 이렇게 올라갑니다. &lt;a href=&quot;https://www.nts.go.kr/nts/cm/cntnts/cntntsView.do?mi=2227&amp;amp;cntntsId=7667&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;(링크)&lt;/a&gt; 이 소득은 기타소득, 사업소득, 근로소득, 배당소득 등 모든 종류의 세금을 합친 소득입니다. &lt;br /&gt;&lt;br /&gt;3. 그런데 개인 A가 실제로 받은 돈은 1000만원에서 3.3%를 제한 967만원인데, 그렇다고 해서 A의 소득이 967만원 혹은 1000만원으로 인정되는게 아닙니다. 사업을 할 때 필요한 비용이 있을 수 있기 때문에 원칙적으로는 필요한 비용을 입증해서 내 소득을 감소시킬 수 있으나, 저희처럼 본격적으로 사업을 하는 사람들이 아니라 어쩌다가 가끔씩 사업소득이 생기는 사람한테까지 필요 경비를 입증하라고 하는건 너무 번거로운 일이기 때문에 세전 수입금액이 2400만원 이하라면 전체 금액 중에서 64.1%을 경비로 인정해줍니다. 즉 개인 A의 소득은 1000만원이 아니라 359만원으로 고려가 됩니다. (관련 키워드 : 기준경비율, 단순경비율, 업종코드 940909)&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;4. 독립가구의&amp;nbsp;세대주(쉽게&amp;nbsp;말해서&amp;nbsp;집에서&amp;nbsp;나와&amp;nbsp;주소지를&amp;nbsp;옮겨놓은&amp;nbsp;사람)가&amp;nbsp;지난&amp;nbsp;한&amp;nbsp;해&amp;nbsp;받은&amp;nbsp;근로소득&amp;nbsp;or&amp;nbsp;사업소득(근로소득은&amp;nbsp;세전,&amp;nbsp;사업소득은&amp;nbsp;경비를&amp;nbsp;제한&amp;nbsp;소득)&amp;nbsp;합이&amp;nbsp;2000만원&amp;nbsp;미만일&amp;nbsp;경우&amp;nbsp;근로장려금을&amp;nbsp;신청해서&amp;nbsp;받을&amp;nbsp;수&amp;nbsp;있습니다.&amp;nbsp;단&amp;nbsp;재산이&amp;nbsp;2억&amp;nbsp;이상일&amp;nbsp;땐&amp;nbsp;못받습니다.&amp;nbsp;하지만&amp;nbsp;근로소득&amp;nbsp;or&amp;nbsp;사업소득이&amp;nbsp;없고&amp;nbsp;기타소득만&amp;nbsp;있을&amp;nbsp;경우에는&amp;nbsp;근로장려금을&amp;nbsp;받을&amp;nbsp;수&amp;nbsp;없습니다.&lt;/p&gt;
&lt;p&gt;&lt;br /&gt;&lt;b&gt;&amp;lt;기타소득&amp;gt;&lt;/b&gt; &lt;br /&gt;1.&amp;nbsp;기타소득은&amp;nbsp;60%를&amp;nbsp;경비로&amp;nbsp;인정해줘서&amp;nbsp;실제&amp;nbsp;받은&amp;nbsp;돈의&amp;nbsp;40%가&amp;nbsp;본인의&amp;nbsp;소득인&amp;nbsp;셈입니다. &lt;br /&gt;&lt;br /&gt;2.&amp;nbsp;기타소득은&amp;nbsp;8.8%를&amp;nbsp;원천징수합니다.&amp;nbsp;하지만&amp;nbsp;사업소득에서&amp;nbsp;언급했듯&amp;nbsp;원천징수하는&amp;nbsp;8.8%는&amp;nbsp;크게&amp;nbsp;의미가&amp;nbsp;없고&amp;nbsp;실제&amp;nbsp;개인이&amp;nbsp;부담해야&amp;nbsp;하는&amp;nbsp;세금이&amp;nbsp;얼마인지가&amp;nbsp;중요합니다. &lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;3. 상금에 의한 소득은 기타소득입니다. 이 때 로또와&amp;nbsp;같이&amp;nbsp;우연에&amp;nbsp;의해&amp;nbsp;정해지는&amp;nbsp;이득은&amp;nbsp;세금이&amp;nbsp;22%이지만&amp;nbsp;다수&amp;nbsp;참가자간의&amp;nbsp;경쟁을&amp;nbsp;통해&amp;nbsp;정해진&amp;nbsp;순위로&amp;nbsp;얻은&amp;nbsp;이득은&amp;nbsp;세금이&amp;nbsp;4.4%입니다.&amp;nbsp;간혹&amp;nbsp;대회나&amp;nbsp;공모전&amp;nbsp;주최측이&amp;nbsp;세금을&amp;nbsp;22%나&amp;nbsp;8.8%로&amp;nbsp;착각해&amp;nbsp;정해진&amp;nbsp;것&amp;nbsp;보다&amp;nbsp;더&amp;nbsp;많이&amp;nbsp;제하고&amp;nbsp;지급하는&amp;nbsp;경우가&amp;nbsp;있는데&amp;nbsp;꼭&amp;nbsp;제&amp;nbsp;돈&amp;nbsp;다&amp;nbsp;챙기세요.&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;br /&gt;&lt;b&gt;&amp;lt;종합&amp;gt;&lt;/b&gt; &lt;br /&gt;1. 경비 처리 덕분에 직장을 다니고 있지 않는한(=근로 소득이 없는한) 대부분의 세율은 6%에서 끊긴다고 보면 됩니다. 예를 들어 대학원에서 월 200만원을 받고 한 해동안 사업소득 (세전) 1000만원을 벌었다고 하면 &lt;br /&gt;&lt;br /&gt;기타소득&amp;nbsp;인정금액&amp;nbsp;=&amp;nbsp;2400&amp;nbsp;*&amp;nbsp;0.4&amp;nbsp;=&amp;nbsp;960만원 &lt;br /&gt;사업소득&amp;nbsp;인정금액&amp;nbsp;=&amp;nbsp;1000&amp;nbsp;*&amp;nbsp;0.359&amp;nbsp;=&amp;nbsp;359만원 &lt;br /&gt;&lt;br /&gt;총&amp;nbsp;1319만원이고&amp;nbsp;고작&amp;nbsp;119만원에&amp;nbsp;대해서만&amp;nbsp;15%가&amp;nbsp;붙게&amp;nbsp;됩니다.&amp;nbsp;납부해야&amp;nbsp;하는&amp;nbsp;세금은&amp;nbsp;1200&amp;nbsp;*&amp;nbsp;0.06&amp;nbsp;+&amp;nbsp;119&amp;nbsp;*&amp;nbsp;0.15&amp;nbsp;=&amp;nbsp;89.95만원이&amp;nbsp;됩니다.&amp;nbsp;그렇기&amp;nbsp;때문에&amp;nbsp;총&amp;nbsp;소득이&amp;nbsp;1200만원으로&amp;nbsp;잡힌다면 &lt;br /&gt;&lt;br /&gt;이번&amp;nbsp;건으로&amp;nbsp;세전&amp;nbsp;X를&amp;nbsp;받았을&amp;nbsp;때(실제로&amp;nbsp;통장에는&amp;nbsp;3.3%를&amp;nbsp;제한&amp;nbsp;돈이&amp;nbsp;들어옴)&amp;nbsp;내가&amp;nbsp;부담해야&amp;nbsp;하는&amp;nbsp;세금은 &lt;br /&gt;&lt;br /&gt;사업소득&amp;nbsp;:&amp;nbsp;X&amp;nbsp;*&amp;nbsp;0.359&amp;nbsp;*&amp;nbsp;0.06&amp;nbsp;=&amp;nbsp;0.0215 &lt;br /&gt;&lt;br /&gt;기타소득&amp;nbsp;:&amp;nbsp;X&amp;nbsp;*&amp;nbsp;0.4&amp;nbsp;*&amp;nbsp;0.06&amp;nbsp;=&amp;nbsp;0.024 &lt;br /&gt;&lt;br /&gt;로&amp;nbsp;X에&amp;nbsp;대해서&amp;nbsp;대략&amp;nbsp;2.1-2.4%&amp;nbsp;정도라고&amp;nbsp;생각하면&amp;nbsp;됩니다.&amp;nbsp;이게&amp;nbsp;우리가&amp;nbsp;거의&amp;nbsp;항상&amp;nbsp;종합소득세&amp;nbsp;신고&amp;nbsp;기간에&amp;nbsp;세금을&amp;nbsp;도로&amp;nbsp;환급받는&amp;nbsp;이유이기도&amp;nbsp;합니다.&amp;nbsp;미리&amp;nbsp;떼간건&amp;nbsp;3.3%&amp;nbsp;혹은&amp;nbsp;8.8%인데&amp;nbsp;실제로는&amp;nbsp;2%&amp;nbsp;정도만&amp;nbsp;부담하면&amp;nbsp;되니.. &lt;br /&gt;&lt;br /&gt;&lt;b&gt;&amp;lt;주의사항&amp;gt;&lt;/b&gt; &lt;br /&gt;대학생 or 대학원생이라면 아마 본인이 직접 매달 건강보험료를 납부하는 대신 아버지나 어머니가 납부하시는 건강보험의 피부양자로 등록이 되어있을텐데 사업소득이 500만원 초과(즉 기본율 64.1% 기준 세전 소득이 1392만원 초과)일 경우 건강보험 피부양자 자격이 박탈되어 매달 건강보험료를 납부해야할 수 있습니다. 다만 22년 소득에 대한 집계는 23년에 이루어지고 피부양자 박탈은 24년에 이루어지기 때문에 설령 22년 소득이 기준을 넘어선다고 해도 &lt;span&gt;24년 전에 취업을 할 예정이라면&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;어차피 직장에 들어가면서 건강보험에 자동으로 가입되니 크게 상관없습니다.&lt;/p&gt;</description>
      <category>일상/ETC</category>
      <author>BaaaaaaaaaaaaaaaaaaaaaaarkingDog</author>
      <guid isPermaLink="true">https://baaaaaaaaaaaaaaaaaaaaaaarkingdog.tistory.com/1053</guid>
      <comments>https://baaaaaaaaaaaaaaaaaaaaaaarkingdog.tistory.com/1053#entry1053comment</comments>
      <pubDate>Sun, 15 May 2022 19:11:40 +0900</pubDate>
    </item>
    <item>
      <title>ㅇㄷㅇㅈ</title>
      <link>https://baaaaaaaaaaaaaaaaaaaaaaarkingdog.tistory.com/1051</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;04/13 수&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;snatch 배움&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;04/14 목&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;clean 배움&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;04/15 금&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;60 deadlift (35lbs), &lt;span&gt;60&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;sit up, &lt;span&gt;60&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;box jump over(20inch)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;20:04, 허리 조심해야 한다. 자세 정확하게 해야함&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;04/18 월&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;3R / 30 wall ball (6lbs), 20 box step up with KB (8kg), 15 kettlebell swing russian&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;14:53, 금요일 운동때 아픈 복근이 아직도 다 안풀려서 준비운동때 지옥을 경험함&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;04/19 화&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;EMOM 18min (6R) / &lt;span&gt;1min - 12/10cal row, &lt;/span&gt;&lt;span&gt;1min - 10 knee raise,&amp;nbsp;&lt;/span&gt;&lt;span&gt;1min - 8 thruster (35lbs)&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;-15, 로잉에서 거의 다 나가리됐다&lt;br /&gt;&lt;br /&gt;04/21 목&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;30R / &lt;/span&gt;&lt;span&gt;3 deadlift (35lbs), 3 burpee over bar&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;24:00, &lt;/span&gt;&lt;span&gt;데드리프트 무게 조금 올려도 될듯?&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;04/22 금&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;​4R&amp;nbsp;&amp;nbsp;/ 20 cal row, 10 single arm db pp R &amp;amp; L, 16 alt db snatch (15lbs) &lt;br /&gt;18:54,&amp;nbsp;로잉이&amp;nbsp;생각보다&amp;nbsp;괜찮았음.&amp;nbsp;db&amp;nbsp;pp,&amp;nbsp;db&amp;nbsp;snatch&amp;nbsp;처음&amp;nbsp;해봤는데&amp;nbsp;다음엔&amp;nbsp;무게&amp;nbsp;올려보자&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;04/25 월&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;스쿼트 &lt;/span&gt;&lt;span&gt;32.5kg 5 / 40kg 5 / 50kg 3 / 52.5kg 5 / 62.5kg 1 / &lt;/span&gt;&lt;span&gt;40kg 5x5&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;WOD 안하고 중량스쿼트를 했다. 자세가 이상한건지 유연성이 안좋은건지 어깨쪽이 아픔ㅠ 그래도 아무튼 재밌었다&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;04/26 화&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;120&amp;nbsp;double&amp;nbsp;under,&amp;nbsp;90&amp;nbsp;cal&amp;nbsp;row,&amp;nbsp;80&amp;nbsp;air&amp;nbsp;squats,&amp;nbsp;60&amp;nbsp;wall&amp;nbsp;ball&amp;nbsp;(10lbs),&amp;nbsp;40&amp;nbsp;box&amp;nbsp;jump&amp;nbsp;(24in)&lt;br /&gt;27:30, 유산소 개빡세다. wall ball때 지옥을 봤다. 그래도 완주에 의의를,,,&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;04/27 수&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;​E4MOM 3 deadlift, 6 hang squat clean, 9 thruster (35lbs), 12 cal row&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다 채워서 기분이 굉장히 좋았다. 그런데 뒤로 갈수록 힘딸려서 팔꿈치가 끝까지 못올라가니 손목에 무리가 간듯. 45lbs 될줄 알았는데 45로 해보려고 하니 clean이 안됨&lt;br /&gt;&lt;br /&gt;04/28 목&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;snatch deadlift (55lbs) 7x12&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;어제 힘 딸리는데 어거지로 한 것 때문인지 허리가 아파서 갈까말까 고민했는데 그래도 지금까지 계속 간게 아까워서 오늘도 출석. 맨날 바벨 잡으면 35lbs로 했는데 처음으로 55lbs로 했다. 다만 세트 뒤로 갈수록 snatch 그립으로는 힘이 안되고 꼼수 느낌으로 손이 계속 가까워지긴 했음.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;04/29 금&lt;br /&gt;18amrap(8R)&amp;nbsp;&quot;I&amp;nbsp;go&amp;nbsp;you&amp;nbsp;go&quot;&amp;nbsp;/&amp;nbsp;20&amp;nbsp;double&amp;nbsp;under,&amp;nbsp;6&amp;nbsp;alt&amp;nbsp;dumbbell&amp;nbsp;snatch(9kg),&amp;nbsp;6&amp;nbsp;single&amp;nbsp;dumbbell&amp;nbsp;box&amp;nbsp;step&amp;nbsp;up(9kg)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;저번주엔 15lbs로 했는데 오늘은 9kg로 했다는 점에서 만족,,&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;05/02 월&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;squat 25kg 5 / 30kg 5 / 35kg 3 / 40kg 5 / 45kg 5 / 50kg 7 / 25kg 5*5&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;저번주보다 낮은 무게로 하긴 해서 그런건지 자세도 안정적이고 할만했다. 계속 연습하면 될듯&lt;br /&gt;&lt;br /&gt;05/03 화&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2RFT 8 wall walk, 100 double under / 100 golbet squat(8kg) 50 sit up / deadlift 25kg 5*5&lt;br /&gt;더블언더 할 때 계속 발에 걸렸다. 힘들어서 그런듯. 다음에 줄넘기할땐 긴바지 입고 가야지. 끝나고 데드리프트도 했다&lt;br /&gt;&lt;br /&gt;05/04 수&lt;br /&gt;16amrap(2R + 42) / 21cal row, 15 burpee, 9 strict pull up(purple band)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그린밴드 쓰고 싶었는데 여분이 없어서 퍼플로 했다. 근데 생각보단 잘 올라가지던데.. 풀업도 계속 연습해야겠다.&lt;br /&gt;&lt;br /&gt;05/10 화&lt;br /&gt;15-12-9-6-3 hang squat clean (35 lbs), 라운드 사이 50 double under&lt;br /&gt;더 무겁게 할껄 그랬나 싶기도 하고.. 그래도 오랜만에 하는거니ㅎㅎ..&amp;nbsp;&lt;br /&gt;&lt;br /&gt;05/12 목&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;clean &amp;amp; jerk 배움. 65lbs로 clean이 되긴 하는데 jerk는 익숙해지기까지 좀 걸릴듯&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;05/13 금&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;(TEAM WOD) 100cal row &amp;amp; deadlift hold(85lbs), bench press 배움&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;되게 신선한 방식이었음. 끝나고나니 ㄹㅇ 손아귀에 힘이 다 풀렸음. 벤치프레스도 배웠다. 자세 잡기 어렵더라&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;05/16 월&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;스쿼트 20kg 5 / 25kg 5 / 30kg 3 / 40kg 5 / 45kg 3 / 50kg 8 / 55kg 3 / 60kg 2 / 65kg 2 / 70kg 실패 / 40kg 5x5&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;4R 21&amp;nbsp;over&amp;nbsp;and&amp;nbsp;back&amp;nbsp;dumbbell&amp;nbsp;hop,&amp;nbsp;15&amp;nbsp;single&amp;nbsp;dumbbell&amp;nbsp;front&amp;nbsp;squat,&amp;nbsp;21&amp;nbsp;over&amp;nbsp;and&amp;nbsp;back&amp;nbsp;dumbbell&amp;nbsp;hop,&amp;nbsp;12&amp;nbsp;dumbbell&amp;nbsp;snatch&amp;nbsp;alt,&amp;nbsp;21&amp;nbsp;over&amp;nbsp;and&amp;nbsp;back&amp;nbsp;dumbbell&amp;nbsp;hop,&amp;nbsp;9&amp;nbsp;single&amp;nbsp;dumbbell&amp;nbsp;push&amp;nbsp;press&amp;nbsp;(25lbs)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;스쿼트 1rm을 60kg로 보고 프로그램을 돌렸는데 더 높은 것 같다. 처음으로 2탕 뛰었는데 굉장히 피곤하지만 뿌듯하다.&lt;br /&gt;&lt;br /&gt;05/17 화&lt;br /&gt;30-20-10 sit up, hang squat clean (55 lbs), burpee over the bar&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;벤치프레스 16kg 5 / 25kg 5x5&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;처음에 행스쿼트 35 lbs로 하려다가 55 lbs로 올렸는데 힘들었지만 잘한 선택인듯. 근데 쇄골을 계속 맞긴 했다ㅠㅠ 버피가 이렇게 힘든건지 몰랐는데 앞에서 체력이 다 빠지고 숨이 차오른 상태에서 하려고 하니 굉장히 빡셌다. 그거랑 별개로 벤치도 개인적으로 했는데 아직 자세가 잘 안나오는 느낌이 좀 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;05/18 수&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;로잉 60cal, 스내치 30개 (15 lbs)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;데드리프트 35lbs 5 / 55lbs 5 / 75lbs 5 / 95lbs 5 / 105lbs 5 / 115lbs 5 / 125lbs 5 / 135lbs 5 / 145lbs 실패&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;스내치는 자세 잡기가 참 힘들다. 유연성 문제도 조금 있는 것 같기도 하고. 하다보면 늘겠지. 데드리프트는 신기한게 135lbs는 5번 겨우 할 수 있었는데 145lbs는 딱 느낌이 안될겠다 싶었다. 그래도 제일 첫날에 60kg이 아예 미동도 안했던걸 생각하면 늘었다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;05/19 목&lt;br /&gt;15R, 스내치 데드리프트 3, 스내치 풀 2, 행 스내치 1 (15kg)&lt;br /&gt;스쿼트 35lbs 5 / 85lbs 5 / 105lbs 5 / 115lbs 5 / 125lbs 5 / 135lbs 2 / 145lbs 2 / 155lbs 1&lt;br /&gt;&lt;br /&gt;스내치를 원래 45lbs로 하려고 했는데, 데드리프트랑 풀은 다 괜찮았지만 행 스내치가 안되어서 35lbs로 낮춰서 했다. 스쿼트는 155lbs(=70kg) 될까 했는데 1개 성공했다. 1개 더 하려고 했는데 못올라오고 드랍ㅎㅎ,,&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;05/20 금&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;벤치 20kg 5 / 30kg 5 / 20kg 5*4 / 25kg 5*2 &lt;br /&gt;덤벨스내치&amp;nbsp; 9kg 12&amp;nbsp; / 12kg&amp;nbsp;12*2 &lt;br /&gt;철봉매달리기&amp;nbsp; 30초*4 &lt;br /&gt;덤벨로우 10kg&amp;nbsp;양쪽&amp;nbsp;각각&amp;nbsp;10*3&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;벤치 자세 어케 잡는건지 모르겠음ㅠㅠ 바벨 좌우로 움직이고 난리도 아니었다&lt;br /&gt;&lt;br /&gt;05/23 월&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;스쿼트 20kg 5 / 40kg 5 / 50kg 5 / 55kg 5 / 60kg 5 / 65kg 5 / 70kg 3 / 40kg 5x5&lt;br /&gt;철봉 매달리기 30s&amp;nbsp;*&amp;nbsp;4&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;토 or 일중 하루는 운동을 하려했는데 너무 바빠서 못했다. 그래도 이틀 쉬어서 그런가 처음에 뭔가 잘 올라가는 느낌이었다. 70kg 마지막 올릴때 복압이 문젠지 허리가 제대로 못받쳐주는 느낌이 들어 무게를 더 안올렸다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;05/24 화&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;데드리프트 20kg 5 / 40kg 5 / 50kg 5 / 55kg 5 / 60kg 5 / 65kg 5 / 70kg 2 / 75kg 실패 / 45kg 5x5&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;악력이 털린다는게 뭔 느낌인지 알게됐다. 정신적 피로에 육체적 피로가 더해지니 집 도착했을때 진짜 정신이 혼미하다. 바로 꿀잠 때릴 수 있겠다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;05/25 수&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;벤치프레스 20kg&amp;nbsp;5&amp;nbsp;/&amp;nbsp;30kg&amp;nbsp;5&amp;nbsp;/&amp;nbsp;35kg&amp;nbsp;2&amp;nbsp;/&amp;nbsp;25kg&amp;nbsp;5x5 &lt;br /&gt;벤치프레스 머신 35kg&amp;nbsp;5x3&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;벤치가 개약하다&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;06/07 수&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;60&amp;nbsp;burpee&amp;nbsp;over&amp;nbsp;bar&amp;nbsp;/&amp;nbsp;40&amp;nbsp;russian&amp;nbsp;kettlebell&amp;nbsp;swing(16kg)&amp;nbsp;/&amp;nbsp;30&amp;nbsp;front&amp;nbsp;squat(20kg)&amp;nbsp;/&amp;nbsp;10&amp;nbsp;push&amp;nbsp;press(20kg) &lt;br /&gt;&lt;br /&gt;squat 45lbs 5 / 95lbs 5 / 115lbs 6 / 125lbs 3 / 85lbs 5x3&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;오랜만에 했다. 케틀벨 스윙은 처음에 16kg가 좀 무거운 느낌이라 낮출까하다가 그냥 그대로 했는데 그냥저냥 할만했다. push press는 자세가 이상한지 손목이 너무 아팠다. 와드를 한 다음에 스쿼트를 한거였기도 하고 또 되게 오랜만에 한거다보니 중량을 쭉쭉 올리지는 않았다. 등을 확실하게 조일 필요가 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;06/16 목&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;handstand 15s * 10&lt;br /&gt;handstand push up(with ab mat 3) 15s * 10&lt;br /&gt;벤치 7kg 5 / 20kg 5 / 25kg 5 / 30kg 5 / 20kg 5x5&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;코로나로 인해 되게 오랜만에 했다. 체조 동작들 재밌다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;06/17 금&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;15-12-9-6-3 snatch deadlift, knee raise, snatch (35 lbs)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;deadlift 20kg&amp;nbsp;5&amp;nbsp;/&amp;nbsp;34kg&amp;nbsp;5&amp;nbsp;/&amp;nbsp;40kg&amp;nbsp;5&amp;nbsp;/&amp;nbsp;50kg&amp;nbsp;5&amp;nbsp;/&amp;nbsp;60kg&amp;nbsp;5&amp;nbsp;/&amp;nbsp;40kg&amp;nbsp;5&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다음엔 스내치 무게 좀 더 올려도 될듯? 데드리프트 영상 찍어서 보니 허리가 말려서 가슴을 잘 내밀어야 한다&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;06/18 토&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;3R, 400m run / 덤벨스내치 24 (30lbs) / 이단뛰기 40(1R에만 90)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;ohp 7kg 5 / 15kg 5 / 20kg 5 / 15kg 5x4&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이단뛰기할때 계속 줄에 걸렸다. 연습을 더 해야겠지..? 덤벨스내치는 처음으로 30lbs 써서 해봤는데 힘들었지만 할만했다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;06/19 일&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;squat 20kg 5 / 40kg 5 / 50kg 5 / 55kg 5 / 60kg 5 / 65kg 3 / 70kg 2&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;bench press 20kg 5 / 30kg 5 / 40kg 5 / 30kg 5x5 &lt;br /&gt;db row 20lbs 12 / 25lbs 12 / 30lbs 12 / 25lbs 12x3&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;헬스장 처음 가봄&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;06/21 화&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;deadlift(sling rack) 20kg 5 / 40kg 5 / 50kg 5 / 60kg 5 / 65kg 5 / 70kg 5 / 75kg 1 / 45kg 5x5 &lt;br /&gt;ohp&amp;nbsp;10kg&amp;nbsp;5&amp;nbsp;/&amp;nbsp;20kg&amp;nbsp;5&amp;nbsp;/&amp;nbsp;25kg&amp;nbsp;5&amp;nbsp;/&amp;nbsp;15kg&amp;nbsp;5x5&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;지금까진 그냥 맨손으로 했지만 이젠 스트랩이 필요하다. 손이 계속 풀림&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;06/23 목&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;squat 20kg 5 / 40kg 5 / 50kg 5 / 60kg 5 / 65kg 5 / 70kg 2 / 45kg 5x5 &lt;br /&gt;bench press 20kg 5 / 25kg 5 / 30kg 5 / 35kg 3 / 30kg 5x5&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;06/29 수&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;6R 40 DU, 10cal rowing,10 knee raise&lt;br /&gt;squat 45lbs 5 / 75lbs 5 / 105lbs 5 / 125lbs 5&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;06/30 목&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;front squat 45lbs 1 / 75lbs 1 / 95lbs 1 / 115lbs / 135 lbs 1 / 145lbs 실패 / 65lbs 10 9 8 7 6 5 4 3 2 1&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;07/01 금&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1-2-3-4-5-6-7-8 1 wall ball (12 lbs), 1&amp;nbsp;burpee&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;bench press 45lbs 5 / 65lbs 5 / 85lbs 2 / 65lbs 5x5&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;어제 한것때문인지 복근 많이 땡겼음. wall ball이 ㄹㅇㄹㅇ 힘듬. 벤치는 잘 늘지가 않는다ㅠ&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;07/04 월&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;(오전)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;4/4/4/4/4 wall walk&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;50/40/30/20/10 air squat, DU&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;deadlift 45lbs&amp;nbsp;1&amp;nbsp;/&amp;nbsp;65lbs&amp;nbsp;5&amp;nbsp;/&amp;nbsp;95lbs&amp;nbsp;5&amp;nbsp;/&amp;nbsp;115lbs&amp;nbsp;5&amp;nbsp;/&amp;nbsp;135lbs&amp;nbsp;5&amp;nbsp;/&amp;nbsp;155lbs&amp;nbsp;1&amp;nbsp;/&amp;nbsp;85lbs&amp;nbsp;5x3&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;(오후)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;ohp 10kg 5 / 20kg 5 / 25kg 5 / 30kg 5 / 20kg 5x5&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;db row 8kg 12 / 10kg 12 / 13kg 12x3&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;30분 수영&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;더블언더 이제 잘됨ㅎㅎ&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;07/05 화&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;burpee over the bar 30, hang power clean 50 (55lbs), wall&amp;nbsp;ball&amp;nbsp;100&amp;nbsp;(10lbs) &lt;br /&gt;&lt;br /&gt;squat 45lbs 5 / 75lbs 5 / 105lbs 5 / 125lbs 5 / 145lbs 3 / 155lbs 실패 / 85lbs 5x5&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;07/06 수&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;thruster 140 (35lbs) &lt;br /&gt;bench press 45lbs 5 / 65lbs 5 / 75lbs 1 / 65lbs 5x5&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;하체 박살..&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;07/07 목&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;ohp 45lbs 3 / 55lbs 1 / 75lbs 1 / 85lbs 1 / 45lbs 7x5 &lt;br /&gt;push press 65lbs 1 / 75lbs 1 / 85lbs 1 / 45lbs 7x5&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;허리 접히는 느낌 들었음.. 코어 잘 잡아야한다. 푸쉬프레스 1rm이 더 나와야 정상인데 아직 협응력이 부족한가?&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;07/11 월&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Double under 200, Box jump over 70, push press 70(45 lbs)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;squat 45lbs 5 / 95lbs 5 / 125lbs 5 / 145lbs 5 / 155lbs 3 / 165lbs 2 / 175lbs 1(PR!) / 95lbs 5x5&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;사실 double under랑 push press는 저 개수보다 더 많이 하긴 함ㅎㅎ.. 좀 쉬다 와서 그런가 스쿼트가 쭉쭉 늘어났다. 이제 3대 200 도달한것같기도..?&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;07/12 화&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;12 burpee over the bar * 4, 10 power snatch(45lbs) * 7&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;밤에 갔어서 추가운동은 못함. B가 65여서 65를 하고싶었지만 택도 없었다ㅠ 세컨풀이 영 이상해서 바벨이 몸에 붙은 상태로 올라가는게 아니라 그냥 무릎에서 위로 올리는 상황이었음. 교정이 필요함&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;07/13 수&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;5R 10 thruster(55lbs) 15 pull up(green band) 10 thruster 35 double under&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;bench press 35lbs&amp;nbsp;5&amp;nbsp;/&amp;nbsp;55lbs&amp;nbsp;5&amp;nbsp;/&amp;nbsp;65lbs&amp;nbsp;5&amp;nbsp;/&amp;nbsp;75lbs&amp;nbsp;5&amp;nbsp;/&amp;nbsp;85lbs&amp;nbsp;2&amp;nbsp;/&amp;nbsp;55lbs&amp;nbsp;5x5&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2R쯤에 과연 이걸 정말 끝낼수있을까 싶었는데 어째저쨰 끝내긴 했다. 쓰러스터할때 손목 아팠음. 그리고 키핑풀업 아직 느낌을 못잡겠다. 벤치는 1RM 100lbs는 나올줄 알았는데 85lbs로 3번이 힘들었음.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;07/14 목&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;10R&amp;nbsp;first&amp;nbsp;pull&amp;nbsp;1,&amp;nbsp;deadlift&amp;nbsp;1,&amp;nbsp;high&amp;nbsp;pull&amp;nbsp;1,&amp;nbsp;clean&amp;nbsp;1(75lbs) &lt;br /&gt;5R&amp;nbsp;squat&amp;nbsp;clean&amp;nbsp;1,&amp;nbsp;power&amp;nbsp;clean&amp;nbsp;1&amp;nbsp;(75lbs) &lt;br /&gt;deadlift 75lbs 5 / 105lbs 3 / 135lbs 1 / 155lbs 1 / 165lbs 1 / 95lbs 5x3&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;clean을 95lbs로 할 수 있지 않겠나 싶었는데 막상 할라니까 잘 안됐음. 그리고 거울 보면서 데드리프트 할 때 등 굽는걸 방지하려면 가슴을 진짜 최대한 활짝 열어야한다는걸 느꼈다. 165lbs에서 더 올릴수 있을것 같기도 하다 싶으면서도 뭔가 좋은 자세로 한다기보다는 어거지로 하는 느낌이 있어서 무게를 더 올리지는 않았다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;07/18 월&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;4R 10 DB deadlift, 10 DB hang clean, 10 DB push press, 10 DB front squat (25lbs)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;ohp&amp;nbsp;35lbs&amp;nbsp;5&amp;nbsp;/&amp;nbsp;55lbs&amp;nbsp;5&amp;nbsp;/&amp;nbsp;65lbs&amp;nbsp;5&amp;nbsp;/&amp;nbsp;45lbs&amp;nbsp;5x5&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;옛날에 덤벨스내치를 30lbs로 한적이 있었어서 30lbs를 해보고 싶었지만 push press가 도저히 힘들어서 그냥 25lbs로 진행했다. B 가기도 힘드네ㅎㅎ... 네 동작 중에서 push press가 가장 빡셌다. ohp는 특이사항x&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;07/19 화&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;3R 100 double under / 10 squat clean (85 lbs)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;squat&amp;nbsp;65lbs&amp;nbsp;5&amp;nbsp;/&amp;nbsp;85lbs&amp;nbsp;5&amp;nbsp;/&amp;nbsp;105lbs&amp;nbsp;5&amp;nbsp;/&amp;nbsp;125lbs&amp;nbsp;5&amp;nbsp;/&amp;nbsp;85lbs&amp;nbsp;5x3&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;DU 계속 걸림ㅠ 또 squat clean에서 다리를 써서 그런가 스쿼트가 잘 안됨. 디로딩한다는 느낌으로 살랑살랑 했다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;07/20 수&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;3R 1MIN wall ball(12 lbs), sumo deadlift high pull, box jump, push press(45 lbs), rowing&amp;nbsp;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;bench press 35lbs 5 / 45lbs 5 / 55lbs 5 / 65lbs 5 / 75lbs 5 / 85lbs 5 / 95lbs 2 / 55lbs 5 / 65lbs 5x4&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;푸쉬프레스 55로 할땐 진짜 안밀어지던데 45로 하니까 그냥저냥 와드로 할만했다. 독특한 방식이었는데 재밌었다. 벤치는 95lbs니까 진짜 어거지로 올린다는 느낌이 들었다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;07/25 월&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;(team of 2) 100 deadlift(75lbs), 60 sit up, 100 power clean(65lbs), 60 sit up&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;deadlift 65lbs 5 / 95lbs 5 / 115lbs 5 / 135lbs 5 / 155lbs 2 / 165lbs 2 / 175lbs 1&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;허리 신경 많이 써야한다. 처음으로 DNF ㅠㅠ 대충 3개월만에 드디어 3대 445lbs = 201.8kg 도달했네,,,&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;07/26 화&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2 rounds 30 thrusters (55lb), 30 bar-facing burpees then Max cal row in remainning time &lt;br /&gt;ohp 35lbs 5 / 45lbs 5 / 55lbs 5 / 65lbs 5 / 55lbs 5x5&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;지금까지 크로스핏하는 동안 처음으로 와드 끝나고 속이 울렁거렸다. 로잉을 너무 열심히 탔나ㅎㅎ.. 그래도 로잉이 되게 오랜만이었는데 1400 1500 찍혀서 신기했다. ohp할 때 옆에서 자세를 봐주시는 분들이 이것저것 알려주셔서 좋았다. ohp 75lbs는 분명 들만했을텐데 들리지가 않아서 아쉬웠다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;07/27 수&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;50 double under 14 box jump over(30inch)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;squat 45lbs 5 / 75lbs 5 / 105lbs 5 / 135lbs 5 / 155lbs 3 / 175lbs 1 / 105lbs 5x3&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;유산소에 자신있다고 생각했는데 그렇지 않았다. double under 계속 걸렸음. 또 30inch box jump는 상당히 힘들었다. 중간에 걸려 넘어지기도 했고 무릎 아픔ㅠ&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;07/28 목&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;bench press 20kg 5 / 30kg 5 / 35kg 5 / 40kg 5 / 30kg 5x5 &lt;br /&gt;턱걸이(보라밴드)&amp;nbsp;5&amp;nbsp;5&amp;nbsp;3&amp;nbsp;3&amp;nbsp;3&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;벤치 더 늘면 좋겠다&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;07/29 금&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;4R 21 db over&amp;amp;back hop 21 db snatch alt 15 db over&amp;amp;back hop 15 db hang power clean 9 db over&amp;amp;back hop 9 db front squat(25lbs)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;deadlift 75lbs 5 / 105lbs 5 / 135lbs 5 / 155lbs 3 / 105lbs 5x5&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;데드할때 허리말림에 신경을 정말 많이 썼더니 이전과는 다른 느낌으로 할 수 있었다. 덤벨을 30으로 하고싶었는데 30으로 하니 snatch가 너무 힘든 느낌이었다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;08/01 월&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;ohp&amp;nbsp;20kg&amp;nbsp;5&amp;nbsp;/&amp;nbsp;25kg&amp;nbsp;5&amp;nbsp;/&amp;nbsp;30kg&amp;nbsp;5&amp;nbsp;/&amp;nbsp;35kg&amp;nbsp;4&amp;nbsp;/&amp;nbsp;25kg&amp;nbsp;5x5 &lt;br /&gt;pull&amp;nbsp;up(purple&amp;nbsp;band)&amp;nbsp;5&amp;nbsp;5&amp;nbsp;5&amp;nbsp;4&amp;nbsp;3&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;15R 3 power clean(95lbs) 6 push up 9 air squat&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;squat 45lbs 5 / 95lbs 5 / 125lbs 5 / 145lbs 5 / 165lbs 3 / 175lbs 2 / 185lbs 1 / 115lbs 5x5&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;B라니 매우 감동이다. 스쿼트도 1rm 갱신함&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;08/02 화&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;(synchro) thruster(55lbs), russian kettlebell swing(16kg), bupree&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;bench press &amp;nbsp;45lbs 5, 65lbs 5, 85lbs 3, 95lbs 1, 65lbs 5x5&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;쓰러스터 더 높이고 싶었는데 어제 ohp를 해서 그런가 어깨가 많이 힘들었다. 벤치할때 손목 조심해야 한다. 95할 때 느낌 살짝 안좋았음. 벤치할때 등을 더 띄우라는 조언을 들었다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;08/03 수&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;snatch 30(55lbs)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;deadlift 45lbs 5 / 95lbs 5 / 125lbs 5 / 155lbs 3 / 95lbs 5x5&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;스내치는 아직 동작이 안익숙하다. 락아웃이 제대로 안걸려서 무게를 더 못 높혔음.데드리프트는 1rm까지 가고싶어서 초반에 무게를 공격적으로 올렸는데 허리가 말리는 느낌도 들고 이번주에 운동을 너무 빡세게 해서 그런가 많이 힘들어서 155lbs에서 멈췄다. 고중량으로 가면 어쩔수없이 말리는건지 힙드라이브가 부족한건지 조언을 구해봐야 할듯&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;08/04 목&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;4R 30 double under, 20 dumbbell goblet squat, 10 devil press alt(35lbs)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;ohp 45lbs 5 / 55lbs 5 / 65lbs 5 / 75lbs 3 / 55lbs 5x5&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;피로가 너무 쌓였는지 영 잘 안됐다. 데드리프트 자세 열심히 배우긴했는데 쉽지 않음. 머리로는 알겠는데.. ohp도 이래저래 조언 많이 들었음&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;08/05 금&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;18R 5 pull up(green band), 10 push up, 15 air squat&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;squat 45lbs 5,95lbs 5,125lbs 5,145lbs 5,165lbs 3,115lbs 5x5&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;맨처음 EMOM 30R인거 보고 기겁했음. push up이 가장 병목이었고 뒤로 가면 갈수록 정자세가 아니었음ㅎㅎ.. 턱걸이를 등으로 땡긴다는 느낌을 아직 모르겠긴한데 일단 대충 어떻게 해야하는지는 알겠다. 스쿼트는 좀 쉬엄쉬엄 했음. 일주일 열심히 해서 그런가 피로가 많이 쌓임&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;08/08 월&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Wall ball 2 4 6 8 10 12 14 (14lbs), burpee 2 2 4 4 6 6 8 8 10 10 12 12 7&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;bench press 45lbs 5 / 65lbs 5 / 75lbs 5 / 85lbs 5 / 95lbs 2 / 75lbs 5x5&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;숨차서 버피 너무 힘들었음 정신 나갈뻔.. 벤치 자세 잘 배웠다. 이제 스쿼트랑 벤치는 자세가 잘 잡힌듯..?&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;08/09 화&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;5R 20 medicine ball clean(14lbs), 60 double under&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;deadlift 45&lt;span&gt;lbs&lt;span&gt; &lt;/span&gt;&lt;/span&gt;5 / 95lbs 5 / 125lbs 5 / 155lbs 5 / 175lbs 3 lbs 195lbs 1 / 125lbs 5x5&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;더블언더 계속 걸려서 힘들었음 그래도 어케저케 완주는 했다. 데드리프트 자세 허리 안말리고 잘했음&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;08/10 수&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;5R 10 knee raise, 12 row, 10 front squat(65 lbs)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;ohp 45lbs 5 / 65lbs 5 / 75lbs 5 / 55lbs 5x5&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;knee to chest까지는 금방 갈듯.. front squat B가 95lbs였는데 95는 영 안되겠더라. 75는 할수도 있었을텐데 하는 아쉬움이 약간 있긴 하다. 로잉 되게 오랜만이었는데 옛날에 비슷한 EMOM에서 엄청 깎였던것과 달리 이번에는 엥간치 잘 땡겼다. ohp는 75까지는 어째저째 5번 했는데 85에서는 딱 랙에서 뽑으니 오른팔에서 쥐날것같은 느낌이 들어서 올리지 못했다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;08/11 목&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;5R 12 box jump(24inch), 12 wall ball(12lbs), 12 push jerk(65lbs)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;squat 45lbs 5 / 95lbs 5 / 125lbs 5 / 155lbs 3 / 105lbs 5x5&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;push jerk 처음이었음. 어제 저녁에 ohp 한걸 고려해서 무게는 조금 낮게 했다. 아직 무릎 펴는 타이밍과 팔을 펴는 타이밍이 안맞는것같기도...? 5R을 채워서 기뻤다. 스쿼트는 오늘 컨디션이 별로라 무게를 많이 못올렸다. 어제 저녁에 하고 바로 오늘 아침에 해서 그런가 오늘 하루종일 피곤에 쩔어있었음&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;08/12 금&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;100/80/60/40 Double under, 25/20/15/10 Sit up, 10/8/6/4 clean(95lbs)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Bench press 45lbs 5 / 65lbs 5 / 75lbs 5 / 85lbs 3 / 95lbs 1 / 65lbs 5x5&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;clean 자세에 대해 많이 배웠다. 퍼스트 풀때 무릎이 들어가야 함. 더블언더는 잘되기도 하고 안되기도 하고 잘 모르겠다. rpm 줄넘기 살까.. 벤치는 직전에 한것보단 잘 안됐다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;08/16 화&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;160 Double under, 40 sit up, 45 pull up(green band), 25 dumbbell thruster(25lbs), 60 burpee&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;deadlift 45lbs 5 / 75lbs 5 / 105lbs 5 /135lbs 5 / 165lbs 3 / 185lbs 1 / 195lbs 1 / 125lbs 5x3&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;덤벨 무게 25lbs 할까 30lbs할까 하다가 25lbs 했는데 30 했으면 큰일날뻔. 풀업은 잘땡겼는데 덤벨 쓰러스터때 너무 힘들었다. 데드리프트는 1rm 갱신 실패ㅜ&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;08/17 수&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;4R 20 dumbbell snatch(30lbs), 15 deadlift(105lbs), 10 single db squat&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;ohp 45lbs 5 / 65lbs 5 / 75lbs 3 / 55lbs 5x5&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;B를 하려했으나 4R을 할 자신이 없어서 무게를 낮췄다. 굉장히 잘한 선택이었다. 뒤로 가니까 데드를 허리로 드는 느낌이 좀 있었다. 덤벨스내치를 하니 어깨를 많이 써서 ohp가 잘 안밀어졌다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;08/18 목&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;20R 3 hang power clean, 3 front squat, 3 thruster(65lbs)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;squat 45lbs 5 / 95lbs 5 / 125lbs 5 / 145lbs 5&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;쓰러스터가 가장 병목이었다. 그래도 20R을 다 채우긴 했다. 전날 데드의 영향으로 허리가 아파서 갈까말까 고민했는데 오늘 와드 끝나고 났을 때 굉장히 힘들었다. 그래서 그런지 스쿼트가 정말 안됐다. 온몸이 뿌드득하는 느낌&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;08/19 금&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Russian kettlebell swing 70(16kg), 300 double under, 80?90?100? wall ball(12lbs)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;bench press 45lbs 5 / 65lbs 5 / 75lbs 5 / 85lbs 5 / 95lbs 3 / 105lbs 2 / 65lbs 5 / 70lbs 5x4&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;줄넘기 잘 안걸릴줄 알았는데 엄청 걸렸다. 호흡보다는 어깨가 아팠음. 그래도 완주는 했다. 벤치프레스는 1rm 갱신했다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;08/20 토&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Squat 45lbs 5, 75lbs 5, 95lbs 3, 115lbs 2, 135lbs 2, 155lbs 1, 175lbs 1, 185lbs 1, 195lbs 1, 205lbs 1, 105lbs 6x10&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이전에 185lbs였는데 갱신했다. 랙에서 뽑을때 허리로 뽑으면 안된다는 조언 들었음&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;08/22 월&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;5R &lt;span&gt;250m row, &lt;/span&gt;&lt;span&gt;max right arm dumbbell press(25lbs), &lt;/span&gt;&lt;span&gt;max left arm dumbbell press , &lt;/span&gt;&lt;span&gt;max knee raise&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;ohp 45lbs 5 / 55lbs 5 / 65lbs 5 / 75lbs 5 / 60lbs 5x5&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;토투바는 ㄹㅇ 어케하는거임...? EMOM이었는데 1분에 250m 로잉이 생각보다 더 빡셌다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;08/23 화&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;Thruster 90(65lbs), burpee 50&lt;br /&gt;deadlift 45lbs 5 / 95&lt;span&gt;lbs&lt;span&gt; &lt;/span&gt;&lt;/span&gt;5 / 145lbs 5 / 175lbs 3 / 195lbs 1 / 205lbs 1 / 215lbs 1&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;쓰러스터하다가 이 깨질줄은 몰랐지.. 무게 좀 낮춰서 할걸.. 신박한 와드였긴했는데.. 데드는 1rm 갱신함&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;08/25 목&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;4R 15 push up, 15 snatch deadlift, 15 hang power snatch(45lbs)&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;bench press 45lbs&amp;nbsp;5,&amp;nbsp;65lbs&amp;nbsp;5,&amp;nbsp;75lbs&amp;nbsp;5,&amp;nbsp;85lbs&amp;nbsp;5,&amp;nbsp;95lbs&amp;nbsp;2,&amp;nbsp;70lbs&amp;nbsp;5x5&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;스내치는 정말 어렵다. 부드럽게 올라가기 쉽지 않다. &lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;08/26 금&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;4R 12 one arm db devil press alt, 14 db snatch alt, 16 plank db drag(30lbs)&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;squat 45lbs&amp;nbsp;5,&amp;nbsp;95lbs&amp;nbsp;5,&amp;nbsp;125lbs&amp;nbsp;5,&amp;nbsp;145lbs&amp;nbsp;5,&amp;nbsp;165lbs&amp;nbsp;3,&amp;nbsp;175lbs&amp;nbsp;2,&amp;nbsp;125lbs&amp;nbsp;5x3&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;적절한 한 주의 마지막이었다. 저번주에 205 어케 들었냐,,,&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;08/29 월&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;4R 24 keeping pull up swing(green belt), 9 deadlift(115lbs), 6 bar facing burpee&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;ohp 45lbs 5 / 55lbs 5 / 65lbs 5 / 75lbs 5 / 55lbs 5x5&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;데드 135로 하고싶었는데 ㄲㅂ&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;09/01 목&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;bench press 20kg 5 / 30kg 5 / 35kg 5 / 40kg 5 / 30kg 5x5&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;pull up(purple belt) 5x5&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;09/05 월&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;70 squat clean(75lbs)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;deadlift 65lbs 5 / 95lbs 5 / 125lbs 1 / 155lbs 1 / 185lbs 1 / 125lbs 5x5&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;무릎 조금 아파서 쉬다가 오랜만(=1주일만?)에 다시 운동했다. 스쿼트클린 95로 하고 싶었는데 조금 빡세서 그냥 75로 선회했다. 힘들긴한데 이게 운동이지 꿀잠 가능&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;09/06 화&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #000000;&quot;&gt;5R 21 dumbbell over and back hop, &lt;span style=&quot;background-color: #ffffff; color: #000000;&quot;&gt;18 plate GTO(35lbs), &lt;span style=&quot;background-color: #ffffff; color: #000000;&quot;&gt;15 single dumbbell front squat(17.5kg)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #000000;&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #000000;&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #000000;&quot;&gt;ohp 45lbs 5 / 65lbs 5 / 75lbs 3 / 55lbs 5x5&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #000000;&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #000000;&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #000000;&quot;&gt;인바디 좀 충격ㅠㅠ.. GTO 처음 해봤는데 처음엔 할만하다 싶었지만 뒤로 갈수록 굉장히 힘들었다. 어깨 빡세게 썼음.&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #000000;&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #000000;&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #000000;&quot;&gt;09/13 화&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;span style=&quot;background-color: #ffffff;&quot;&gt;5R 10 deadlift(115lbs), 10 burpee over the bar / 28 pull up(green band)&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;span style=&quot;background-color: #ffffff;&quot;&gt;ohp 45lbs 5 / 55lbs 5 / 65lbs 5 / 75lbs 4 / 60lbs 5x4&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;span style=&quot;background-color: #ffffff;&quot;&gt;sit up 10x3&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;span style=&quot;background-color: #ffffff;&quot;&gt;확실히 사람이 운동을 해야 긍정적인 에너지가 생김ㅎㅎ.. 복근에서 쥐나는건 처음 겪어봄. 인바디는 안재봤는데 체해서 제대로 못먹은것때문에 근손실 많이 났을것같음&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;span style=&quot;background-color: #ffffff;&quot;&gt;ㅜ&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;span style=&quot;background-color: #ffffff;&quot;&gt;09/14 수&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;span style=&quot;background-color: #ffffff;&quot;&gt;10R 5 thruster(75lbs), 30 double under&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;span style=&quot;background-color: #ffffff;&quot;&gt;deadlift 75lbs 5 / 95lbs 5 / 115lbs 5 / 125lbs 3 / 145lbs 5 /165lbs 5 / 175lbs 1&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;span style=&quot;background-color: #ffffff;&quot;&gt;sit up 10x2&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;span style=&quot;background-color: #ffffff;&quot;&gt;데드할때 허리쓰지말고 힙힌지 잘 쓰도록 정말 조심해야함. 쓰러스터 처음으로 75로 했다. 좀 빡세긴했는데 아무튼 어케저케 끝냄. 더블언더는 이제 굉장히 스무스하게 잘된다. 복근 쥐나는거 2번째로 겪음. 오늘은 진짜 개아팠다. 내일 sit up 있던데 조심해야겠다..&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;span style=&quot;background-color: #ffffff;&quot;&gt;09/15 목&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;span style=&quot;background-color: #ffffff;&quot;&gt;4R 1min cal row, 1min sit up, 1min wall ball(14lbs)&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;span style=&quot;background-color: #ffffff;&quot;&gt;bench press 45lbs 5, 55lbs 5, 65lbs 5, 75lbs 10, 85lbs 1, 95lbs 1, 105lbs 1, 110lbs 1&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;span style=&quot;background-color: #ffffff;&quot;&gt;EMOM은 뭐 힘들게 잘 했고 벤치 115가 될줄 알았는데 못들어서 아쉽다. 그래도 110은 성공함.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;span style=&quot;background-color: #ffffff;&quot;&gt;09/16 금&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;span style=&quot;background-color: #ffffff;&quot;&gt;Squat 45lbs 5 / 75lbs 3 / 105lbs 3 / 135lbs 1 / 155lbs 1 / 175lbs 1 / 185lbs 1 / 195lbs 1 / 205lbs 1 / 155lbs 5x5&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;span style=&quot;background-color: #ffffff;&quot;&gt;1rm 갱신에는 실패했지만 그래도 현상 유지했다. 75%로 5x5하니 허벅지가 ㄹㅇ 불타오르는 느낌이었다.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;span style=&quot;background-color: #ffffff;&quot;&gt;09/19 월&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;span style=&quot;background-color: #ffffff;&quot;&gt;15 kettlebell swing(12kg), 12 burpee pull up, 60 double under&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;span style=&quot;background-color: #ffffff;&quot;&gt;push up 10x5, sit up 10x5&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;span style=&quot;background-color: #ffffff;&quot;&gt;아메리칸 스윙은 처음이었는데 할만했음. 더블언더도 심폐가 딸려서 그렇지 줄넘기 자체는 큰 무리없었음. 버피 풀업이 가장 병목이었음&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;09/20 화&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;40-30-20-10 wall ball shot(14lbs), 40-60-80-100 double under&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;ohp 45lbs 10x2, 55lbs 8x2, 65lbs 5, 75lbs 3x4 &lt;br /&gt;윗몸&amp;nbsp;10x5&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;double under 잘됨, 어깨 탈탈 털렸음&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;09/26 월&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;21-18-15-12 deadlift(115lbs), push up, russian kettlebell swing(16kg)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;squat 75lbs 5, 95lbs 5, 115lbs 3, 125lbs 3, 145lbs 3, 165lbs 7, 175lbs 1, 195lbs 1, 210lbs 1&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;윗몸 12x3&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;09/27 화&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;snatch 연습&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;ohp 35lbs 5, 45lbs 5, 55lbs 5, 65lbs 3, 75lbs 3, 85lbs 2, 65lbs 5x5&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;스내치 정말 어렵다. 등으로 받는다는 느낌을 아직도 잘 모르겠음. ohp는 85를 넘기가 참 쉽지 않다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;09/28 수&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;6R 35 double under, 20 dumbbell squat(30lbs) / 44 dumbbell snatch alt.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;deadlift 75lbs 5, 95lbs 3, 105lbs 3, 125lbs 3, 145lbs 3, 175lbs 4, 175lbs 3&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;데드 175를 들려고 할 때 딱 느낌이 이상해서 많이 못했다. 아마 월화수 내내 데드(랑 비슷한거)가 계속 와드에 들어가서 그런것같음. 와드는 그냥저냥 잘했음. 덤벨스내치는 35부터 뭔가 잘 안되는 느낌이 있었다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;09/29 목&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;5R 18 box jump, 15 thruster(65lbs), 12cal row, 9 burpee&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;bench press 45lbs 5, 55lbs 5, 65lbs 3, 85lbs 3, 95lbs 3, 105lbs 3&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;박스점프와 쓰러스터에서 많이 나가리됐다. 벤치는 가슴 자극을 잘 모르겠음&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;10/03 월&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;squat 75lbs 5, 95lbs 5, 115lbs 3, 145lbs 5, 165lbs 3, 180lbs 5, 195lbs 1, 210lbs 1, 220lbs 1&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;윗몸 15 15 9&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;스쿼트 100kg 감동.. 밧줄타기도 해봤는데 레그리스로 올라가지더라&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;10/07 금&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;bench press 45lbs 5, 65lbs 5, 85lbs 5, 95lbs 5&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;4R 21 row, 15 deadlift(115lbs), 9 handstand push up(2 mat)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;HSPU가 생각보다 잘 됨, 벤치프레스에서 가슴 자극이 잘 안느껴짐, 첫 라운드 HSPU를 마친 후 허리가 살짝 아팠음. 코어에 힘을 줘야하는 것 같음&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;10/10 월&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;squat 75lbs 5, 95lbs 5, 125lbs 3, 145lbs 5, 175lbs 1, 175lbs 3&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;저번주에 좀 쉬었더니 잘 안들림. 5세트때 175 1개하고 못일어났음. 너무 깊이 앉은건가 싶기도 함.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;10/11 화&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;5R 8 strict pull up(green band), 10 ohp(65lbs), 12 knee to chest&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;ohp 45lbs 5, 55lbs 3, 65lbs 3, 75lbs 7, 85lbs 2, 95lbs 1, 100lbs 1&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;ohp 1rm이 상당히 큰 폭으로 개선되었고 아직 토투바는 무리지만 knee to chest까지는 아치 할로우 만들면서 되는 느낌&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;10/12 수&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;75 Power snatch, 50 burpee&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;10/14 금&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;5R 10 thruster(75lbs), 8 box jump&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;bench press 45lbs 5, 55lbs 5, 75lbs 5, 95lbs 7, 105lbs 3, 115lbs 1&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;10/15 토&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;deadlift 40kg 5, 50kg 5, 60kg 5, 70kg 5, 80kg 1&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;영상 찍어보니 자세는 괜찮은데 80kg가 잘 안뽑혀서 굉장히 당황. 데드를 너무 안했나..&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;10/17 월&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;750M row, 50 Deadlift(115lbs), 60 burpee&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Squat 75lbs 5, 95lbs 5, 125lbs 3, 135lbs 3, 155lbs 3, 175lbs 5, 195lbs 1&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;스쿼트가 살짝 잘 안들리는 느낌이 있었음, 처음에 데드리프트 하다가 족저근막에 쥐나는 느낌이 들었음&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;10/18 화&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;300 double under, 4R 10 power clean(95lbs), 20 wall ball(12lbs)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;ohp 45lbs 5, 55lbs 3, 65lbs 5, 75lbs 7, 85lbs 1&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;파워클린 B가 115여서 살짝 욕심이 났으나 95 한번 해보고 빠른 포기. 채워야하는 횟수가 많아서 1개씩 끊어갔다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;10/19 수&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;4 alt dumbbell devil press(30lbs), 6 alt dumbbell snatch, 8 alt dumbbell hang clean&amp;amp;jerk&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;deadlift &amp;nbsp;75lbs 5, 95lbs 5, 115lbs 3, 135lbs 5, 155lbs 5, 175lbs 8, 195lbs 1, 215lbs 1&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;덤벨 35lbs 도달 쉽지않다. 데드리프트는 225 실패함&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;10/20 목&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;7R 9 deadlift(75lbs), 6 hang clean, 3 jerk&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;아침에 일어나서 허리 살짝 안좋아서 갈까말까 고민했는데&amp;nbsp; 밤 되니 괜찮아서 갔음. 저크를 정말 오랜만에 했는데 푸쉬저크는 그냥저냥 할만했음&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;10/31 월&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;5R 20 deadlift(95lbs), 20 jump squat&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;squat 45lbs 5, 75lbs 5, 95lbs 3, 115lbs 3, 145lbs 5, 165lbs 3, 185lbs 2&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;오랜만에 갔다. 다시 열심히 해야지. 스쿼트는 평소보다 잘 안되는 느낌.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;11/01 화&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;20R 3 lateral burpee over the bar, 1 snatch(65lbs)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;ohp&amp;nbsp;45lbs&amp;nbsp;5,&amp;nbsp;55lbs&amp;nbsp;3,&amp;nbsp;65lbs&amp;nbsp;3,&amp;nbsp;75lbs&amp;nbsp;3,&amp;nbsp;85lbs&amp;nbsp;3&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;근육통이 진짜 너무 심했다. 앞허벅지 박살나는 기분. 스내치 정말 어렵다. 75가 잘 안됐음.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;11/03 목&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;TABATA push up, sit up, front lunge&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;deadlift 75lbs 5, 95lbs 5, 115lbs 3, 135lbs 3, 155lbs 3, 175lbs 3, 195lbs 1, 215lbs 1&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;타바타 신박했음. 데드는 225가 안들어올려짐ㅠ&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;11/04 금&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;500m row(400m ski / 1000m bike), 15 sumo deadlift highpull(55lbs), 15 thruster&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;bench press 45 5, 55 5, 65 3, 75 3, 85 3, 95 8, 105 1&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;유산소 쉽지 않았다. 스키로 인해 어깨 야무지게 씀. 벤치는 115 실패&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;11/09 수&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;550m row, 110 snatch(45lbs), 11 ohs&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;deadlift 75lbs 5, 95lbs 5, 115lbs 3, 145lbs 5, 165lbs 3, 185lbs 3, 195lbs 1&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;처음에 ohs 할땐 빈 바로도 빡셌던 것 같은데 유연성이 늘었나보다. 스내치는 개수가 너무 많아서 45로 했는데 잘한것 같기도 하고 조금 늘려도 됐겠다 싶기도 하고.. 데드 215 넘기가 쉽지않다. 195 들때 등의 텐션이 풀리는 느낌. 후면을 강화해야 할듯&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;11/10 목&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;50 wall ball(12lbs), 40 deadlift(100lbs), 30 toes tto bar, 20 burpee, 10 front squat&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;처음으로 토투바 성공했다. 연속은 아직 힘들다. 철봉을 되게 오랜만에 잡았는데 토투바가 되길래 너무 신기했다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;11/11 금&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;(20s on 40s off) 5R burpee over the row, rowing, burpee 6inch, ski, bar face burpee, assert&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;벤치 45lbs 5, 55lbs 5, 65lbs 3, 75lbs 5, 85lbs 3, 95lbs 1, 105lbs 1, 115lbs 1&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;11/14 월&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;squat 75lbs 5, 95lbs 5, 115lbs 3, 135lbs 5, 155lbs 5, 175lbs 5, 195lbs 1, 195lbs 1&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;50-40-30-20-10 sit up, front rack lunge alt(65lbs)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;런지 처음 해봤는데 둔근에 자극이 엄청남. 스쿼트 할 때 175가 원래 AMRAP인데 살짝 평소보다 잘 안들리는 느낌이라 무리는 안했음. 깊이는 괜찮은듯&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;11/15 화&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;ohp 45lbs 5, 55lbs 5, 65lbs 5, 75lbs 5, 85lbs 3&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;40 deadlift(135lbs), 50 wall ball(14lbs), 60 knee to chest&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;데드리프트 155 시도해봤으나 40개는 힘들듯해서 포기, ohp는 65까지는 수월했는데 75부터 급격히 빡셈&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;11/28 월&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;60 row, 50 wall ball(14lbs), 40 dumbbell snatch(30lbs), 30 box jump&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;squat 45lbs&amp;nbsp;5,&amp;nbsp;75lbs&amp;nbsp;5,&amp;nbsp;95lbs&amp;nbsp;5,&amp;nbsp;115lbs&amp;nbsp;3,&amp;nbsp;125lbs&amp;nbsp;5,&amp;nbsp;145lbs&amp;nbsp;5,&amp;nbsp;165lbs&amp;nbsp;2&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2주 안했더니 신체 능력이 떨어진게 확 체감된다. 와드때도 숨이 너무 차서 힘들었고 스쿼트 중량도 잘 안들어졌다. 복구하려면 조금 걸릴듯?&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;11/29 화&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;45 burpee over the bar, 30 cluster(65lbs), 15 strict pull up(black)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;ohp 45lbs 7x2, 75lbs 5 5 3 4 4 4, 45lbs 20&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;sit up 15x2&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;ohp 85가 안들렸다. ㄲㅂ.. 45lbs 20개 죽는줄 알았다. 클러스터도 굉장히 힘들었다. 그나마 풀업이 나았음&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;11/30 수&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;5R 9 devil press(20lbs), 20 dumbbell lunge, 9 dumbbell push press, 20 sit up&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;deadlift 45lbs 5, 75lbs 5, 115lbs 1, 145lbs 1, 195lbs 1, 205lbs 1, 215lbs 1, 220lbs 1&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;스쿼트 데드 둘 다 100kg 도달했음. 225는 안댐. 와드는 데드리프트 하고난 뒤라 그런가 첫 라운드에 이거 뭔가 심상치않다는 느낌이 왔는데 그래도 어찌저찌 5라운드 했음&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;12/01 목&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;5R 12cal row, 10 hang power clean(75lbs), 8 push jerk&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;bench press 45lbs 5, 75lbs 1, 95lbs 1, 115lbs 1, 65lbs 5, 75lbs 5, 85lbs 6&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;와드는 딱 끝낼 수 있게 힘들었음. 벤치프레스는 125에서 깔렸고 120은 시도해보고 싶었으나 또 도와달라고 부르기 민망해서 시도 못함ㅎㅎ;;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;12/05 월&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;front squat 45lbs 3, 95lbs 1, 135lbs 1, 165lbs 1, 185lbs 1&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;3R 21 burpee, 15 squat clean(95lbs), 9 hand stand push up(1 mat)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;sit up 20-15-10-5&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;프론트스쿼트 1rm을 쟀다. 185 진짜 몸 부들부들떨면서 들어올림. 상체가 못버틴다는 조언을 들었다. 랙포지션/백포지션에서 무게 홀드하고 버티는 연습을 해야겠다. 핸드스탠드푸쉬업은 의외로 잘 됐다. 다음엔 스트릭트로 했을 때 매트 몇개 필요한지 봐야겠다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;12/06 화&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;ohp 45lbs 5, 65lbs 1, 85lbs 1, 95lbs 1&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;5R 15 plate GTO(25lbs), 12 box step up with plate, 12 cal row, 20 v-up&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;strict hand stand push up 5 6 7 10 10&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;ohp는 분명 100lbs을 언젠가 든 적이 있었는데,,, 100 105 다 실패함. GTO는 옛날에 35lbs로 한 적이 있었는데 예상치못하게 오히려 step up이 너무 힘들어서 그냥 25lbs로 진행했다. 어제 HSPU 한 기념으로 오늘은 strict를 했는데 굉장히 잘 되어서 놀라웠다. 10개가 그냥 됐음. 핸드스탠드 워크 도전해봐야겠다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;12/08 목&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;21-18-15-9 hang clean(75lbs), push up&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;deadlift 45lbs 5, 75lbs 5, 95lbs 5, 115lbs 5, 135lbs 5, 155lbs 5, 175lbs 7&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;행클린할 때 오른쪽 어깨가 살짝 아파서 경과를 봐야겠다 했는데 다음날 일어나니 괜찮았다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;12/12 월&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Squat 45lbs 5, 75lbs 5, 95lbs 5, 115lbs 5, 135lbs 5, 155lbs 5, 175lbs 1&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;burpee over dumbbell 50, alt. single db reverse lunge(30lbs), db snatch(30lbs)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;스쿼트 중량이 좀 낮아진 느낌이었다. 주말에 ctf하느라 잠 못자서 그런걸로ㅎㅎㅎ;; 덤벨은 계속 30이라 아쉽다&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;12/13 화&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;ohp 45lbs 5, 65lbs 5, 70lbs 4, 80lbs 3, 90lbs 3x3&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;10R 3 squat snatch(45lbs), 5 ring low&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;ohp 마지막셋은 사실 보조 받으면서 들었음ㅎㅎ; 스내치가 너무 어렵다. 자세 자체가 안익숙함. 오른쪽 어깨 아픈 느낌이 계속 있어서 이번주는 쭉 쉬어야겠다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;12/19 월&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Squat 45lbs 5, 75lbs 5, 95lbs 5, 115lbs 5, 135lbs 5, 155lbs 5&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;100 wall ball(14lbs), 4-5min wall sit hold&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;ring low 5x4&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;sit up 20-15-15&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;일부러 일주일정도 쉬었는데도 운동을 하고 나니 어깨 불편한 느낌이 계속 있어서 내일 정형외과 가봐야겠다ㅠ&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1/3 화&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;5R 5 squat clean(75lbs), 10 front rack lunge alt, 50 double under&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;row 100 cal, sit up 20-15-15&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;쉬는동안 피스톨스쿼트 계속 연습했음. 숨이 엄청 찼고 런지가 빡셌다. 바이크보다 로잉이 훨씬 힘들게 느껴졌음&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1/4 수&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;21-18-15-12-9 snatch deadlift(95lbs), push up&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;assert bike 70cal&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;push up 25-15-15&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1/6 금&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;deadlift 45lbs 5, 95lbs 3, 155lbs 1, 185lbs 1, 215lbs 1, 235lbs 1&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;5R 100 double under, 10 deadlift(135lbs)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;bench press 45lbs 5, 75lbs 3, 95lbs 1, 115lbs 1&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;벤치 1rm이 늘었다. 상당히 기분이 좋았다. 더블언더때 숨이 턱밑까지 차올랐다. 그래도 더블언더는 잘됨. 벤치는 잘 안느네.. 확실히 크로스핏에 가슴을 쓰는 동작이 잘 없으니 알아서 계속 꾸준히 해야겠다. 그리고 레그리스 로프클라임 영상 찍음ㅎㅎ,,&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2/2 목&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;50-40-30 wall ball shot(12lbs), single dumbbell devil press(35lbs)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;한달만에 하니까 숨 너무 차고 머리 터질뻔&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2/3 금&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;4R 21 cal assert(or ski), 15 deadlift(95lbs), 9 power clean&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;bench press 45lbs 5, 65lbs 5, 75lbs 5, 95lbs 3, 105lbs 3, 75lbs 5x4&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;스키 칼로리 너무 안올라서 ㄹㅇ 울면서 탔다&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2/6 월&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;4R 14 cal row, 10 dual db power clean(35lbs), 8 handstand push up(1 mat)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;squat 45lbs 5, 95lbs 5, 135lbs 5, 185lbs 1, 215lbs 1, 245lbs 실패, 235lbs 실패, 45lbs 5, 95lbs 5, 125lbs 5x5&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1rm이 상승하지 않았을까 기대하며 235 245를 시도해봤으나 실패ㅜ 다시 프로그램 돌려야지.. 덤벨 파워클린은 40을 시도해봤으나 40은 택도 없었다. 핸푸는 그냥 스트릭트로 했음&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2/7 화&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;4R 10 db front rack lunge(20lbs), 6 strict pull up(black), 20 jump squat, 24 db box step up&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;ohp 45lbs 5, 65lbs 5, 75lbs 5, 85lbs 4, 65lbs 5x3&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;박스 스텝업이 정말 힘들었다. 풀업은 비교적 쉽게 됨.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2/8 수&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1000m row, 10 burpee box jump over, clean &amp;amp; jerk 85lbs 1 105lbs 1&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;deadlift 85lbs 5, 105lbs 5, 125lbs 5, 145lbs 5, 165lbs 5, 185lbs 5, 195lbs 1&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;클린 저크 둘 다 많이 낮음. 클린 115lbs도 좀 이상한 자세로 받았고 저크 잘 안됐음. 스트렝스 더 열심히ㅜ&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2/14 화&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2R (3R 15 cal row, 2/3/4 wall walk), (3R 50 double under, 10/8/6 knee to chest)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;squat 45lbs 5, 85lbs 5, 105lbs 5, 125lbs 5, 135lbs 5, 155lbs 5, 175lbs 5, 195lbs 1, 195lbs 1&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;숨이 매우 찼음. 스쿼트때 무릎 살짝 아팠음&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2/15 수&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;3R 10 db power snatch alt(35lbs), 10 burpee, 8 db box step over, 10 deadlift(115lbs), 50 double under, 6 cal row&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;ohp 45lbs 5, 55lbs 5, 65lbs 5, 75lbs 5, 85lbs 5&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;심박수 201 찍음,,, ohp때 허리 좀 아팠음. 데드 135를 시도해보려 했으나 좀 힘들어서 그냥 115로 했음.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2/16 목&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;밴드풀업 3x20&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;bench press 45lbs 5, 75lbs 5, 75lbs 100, 95lbs 3, 75lbs 8&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;row 5000m&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;벤치 자세 바로 잡음. 이제 손목 아픈게 덜할듯?&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2/18 토&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;60cal row, 48 toes to bar&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;deadlift 75lbs 5, 105lbs 5, 125lbs 5, 145lbs 5, 165lbs 3, 195lbs 3, 205lbs 1&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;23.1 오픈 와드였는데 토투바가 잘 안되어서 아쉽게 월볼샷까지 못갔다. 그래도 앞쪽 동작은 Rxd로 할 수 있어서 다행,,&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2/21 화&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;squat 45 5, 95 5, 135 3, 185 1, 215 1, 135 5, 165 3, 185 3&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;235는 또 실패ㅜ 밴드끼고 머슬업 체험해봤다. 전환 구간이 생각보다 더 힘들었다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2/27 월&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;5 burpee pull up, 10 shuttle run, 10 burpee pull up, 10 shuttle run, 15 burpee pull up, 10 shuttle run, 20 burpee pull up, 10 shuttle run, 17 burpee pull up&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;thruster 95lbs 1, 105lbs 1, 115lbs 1&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;squat 75lbs&amp;nbsp;5,&amp;nbsp;105lbs&amp;nbsp;5,&amp;nbsp;125lbs&amp;nbsp;5,&amp;nbsp;155lbs&amp;nbsp;5,&amp;nbsp;175lbs&amp;nbsp;3,&amp;nbsp;195lbs&amp;nbsp;3,&amp;nbsp;205lbs&amp;nbsp;1&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;23.2 오픈 와드 측정했다. 가벼우니 이런건 잘 하겠지 싶었는데 생각보다 훠ㅓㅓㅓㄹ씬 더 힘들었다. 15분 너무 김.. 쓰러스터는 115까지 성공했는데 영상 찍은걸 보니 허리가 너무 꺾여서 힙드라이브 자세 다시 연습해야 된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2/28 화&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;(100ft dual DB farmers carry(30lbs), 12/10/8/6 kipping HSPU(2 mats)), (20 front rack lunge, 10/15/20 dual DB deadlift)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;ohp 45lbs 10, 55lbs 5, 65lbs 5, 75lbs 5, 85lbs 3&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1km row, 15km assert bike&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;3/2 목&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;3R EMOM 20sec max DB snatch alt(40lbs), max DB hang&amp;nbsp; clean alt, pistol squat, DB hang clean &amp;amp; jerk&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;deadlift 45lbs 5, 75lbs 5, 95lbs 5, 125lbs 5, 155lbs 5, 175lbs 3, 205lbs 1, 225lbs 1&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;5km row&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;덤벨 35가 딱 잡고 스내치 했을 때 할만해서 오늘 뭔가 날인가 싶었다. 앞으로 덤벨 와드 40으로 할 수 있을듯. 데드는 245 실패&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;3/3 금&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;5 wall walk, 50 double under, 15 snatch(45lbs), 5 wall walk, 50 double under, 5 snatch(65lbs)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;bench press 45lbs 5, 65lbs 5, 85lbs 3, 105lbs 1, 75lbs 5, 85lbs 3, 95lbs 3, 105lbs 2&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;23.3 오픈 와드에서 스내치 무게 너프시켜서 수행함ㅠㅠ 근력 운동 열심히 해야지..&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;3/6 월&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;5R 8 db front squat(30lbs), 8 db front rack lunge step, 8 devil press, 8 db overhead lunge step&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;squat 75lbs 5, 105lbs 5, 125lbs 5, 155lbs 5, 185lbs 3, 205lbs 1&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;assert bike 10km&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;오버헤드런지 상당히 힘들었다&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;3/7 화&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;4R 8 commando pull up, 21 push up, 48 double under&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;ohp 45lbs 5, 55lbs 5, 65lbs 5, 75lbs 5&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;row 5km&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;처음에 코만도풀업 동작만 보고 일반 풀업보다 쉬울줄 알았는데 체감상 더 어려웠다. 레그리스 로프클라임에서 쓰이는 동작이랑 같다고 하니 이해가 갔다. 와드 끝나고 ohp 하려고 하니 말그대로 팔이 안올라가짐&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;3/9 목&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;deadlift 45lbs 5, 75lbs 5, 105lbs 3, 135lbs 2, 165lbs 2, 195lbs 2, 225lbs 1, 245lbs 1, 135lbs 5, 165lbs 5, 185lbs 5&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Clean &amp;amp; Jerk 85lbs로 계속 연습&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;assert bik 10km&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;데드 1rm 갱신함. 영상 찍어보니 자세도 굉장히 괜찮았다. 저크가 좀 안익숙해서 어깨 단련 더해야겠다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;3/21 월&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;5min (50 Goblet squat(24kg), AMRAP burpee / 50 sit up, AMRAM RUS. KB Swing / 50 ALT. Goblet lunge, AMRAP Box jump)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Squat 45lbs 5, 75lbs 5, 105lbs 5, 125lbs 5&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;오랜만에 하는거라 스쿼트는 가볍게만 했다. 케틀벨은 16kg로 할까 24kg로 할까 고민하다가 그냥 24kg로 했는데 상당히 힘들었다ㅎ;;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;3/22 화&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;TABATA double under, 5R 5clean(115lbs), 10 burpee over the bar then 100 double under&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;ohp 45lbs 10, 65lbs 5, 85lbs 3, 105lbs 1&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;3/27 월&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;ski 2000m, 21-15-9 pull up(purple band), handrelease push up, air squat&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;45lbs 5, 75lbs 5, 105lbs 5, 135lbs 5, 155lbs 5, 175lbs 5, 195lbs 2&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;스키 이제 좀 타는 법을 이해함&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;3/28 화&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;push press 45lbs 10, 65lbs 8, 85lbs 6, 105lbs 4x4&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;100 double under, 3R (dual devil press(30lbs), 10 dual db clean), 100 double under&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;3/31 금&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;4km run&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;5R 15 burpee, 20 muscle snatch(45lbs)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;머슬 스내치 영상 보니 바패스가 일직선이 아니었음. 뒤로 날아가는걸 주의&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;4/1 토&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;deadlift 45lbs 5, 115lbs 3, 165lbs 1, 215lbs 1, 145lbs 5, 165lbs 5, 185lbs 5&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;EMOM 28 15cal row, 15 knee to chest, 15cal row, 5 clean(95lbs)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;데드 255 실패ㅠ 그리고 로잉 15cal 절대 못채움.. 이거 어케함..&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;4/3 월&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;squat 45lbs 10, 95lbs 5, 135lbs 5, 185lbs 3*3&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1000m row, 3R 20 wall ball(14lbs), 20 burpee box jump over&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;bench press 45lbs 5, 75lbs 1, 95lbs 1, 105lbs 1, 125lbs 1, 75lbs 5, 85lbs 5, 95lbs 5&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;숨이 너무 찼다. 벤치 1rm 갱신함&lt;br /&gt;&lt;br /&gt;4/4 화&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;ohp 45lbs 10, 65lbs 10x4&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;30-20-10 row, 15-15-15 deadlift(115lbs), 10-10-10 hang power clean&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;4/7 금&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;3R 30 double under, 20 back rack lunge(55lbs), 25-20-15 overhead squat&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;deadlift 55lbs 10, 85lbs 8, 115lbs 5, 135lbs 3, 155lbs 3, 175lbs 3, 195lbs 5&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;4/8 토&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;bench press 45lbs 7, 55lbs 5, 65lbs 5, 75lbs 3, 85lbs 3, 95lbs 3, 105lbs 3&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;push jerk 45lbs 5, 65lbs 3, 85lbs 3, 105lbs 2&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;4/10 월&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;squat 45lbs 5, 95lbs 5, 115lbs 8, 135lbs 8, 155lbs 6, 175lbs 6&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;front squat 115lbs 5, 130lbs 5, 140lbs 5, 150lbs 5&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;3R 16cal ski, 20 air squat, 20 strict HSPU&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;4/11 화&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2R 15-10-5 burpee over the bar, toes to bar, deadlift(135lbs)&lt;br /&gt;ohp 45lbs 10, 65lbs 8, 75lbs 8x2, 65lbs 8 &lt;br /&gt;push&amp;nbsp;press&amp;nbsp;65lbs 10, 65lbs 8x3 &lt;br /&gt;bench&amp;nbsp;press&amp;nbsp;45lbs&amp;nbsp;8,&amp;nbsp;65lbs&amp;nbsp;6,&amp;nbsp;85lbs&amp;nbsp;5x2&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;4/14 금&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;3R 50 double under, 10 snatch(75lbs), 10 pull up(purple) / 100 double under, 20 snatch(65lbs), 20 pull up(purple)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;40min Run&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;bench press 45lbs 5, 55lbs 5, 65lbs 5, 85lbs 5, 95lbs 3, 105lbs 3&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;4/17 월&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;squat 45lbs 5, 115lbs 3, 165lbs 1, 215lbs 1, 235lbs 1, 245lbs 1(이지만 깊이가 조금 부족,,), 125lbs 5, 155lbs 5&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;3R row 15 cal, 20 dumbbell lunge(40lbs) alt, 20 dumbbell snatch alt, 15 push up&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;스쿼트 1rm 갱신에 되게 오래걸렸다&lt;br /&gt;&lt;br /&gt;4/19 수&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;row 100m, 6R 3 deadlift(175lbs), 8 russian kettle bell swing(16kg), 12 box jump, 15 burpee&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;deadlift 45lbs 10, 115lbs 8x3, 165lbs 6x2, 195lbs 5x3 &lt;br /&gt;ohp&amp;nbsp;45lbs&amp;nbsp;5,&amp;nbsp;55lbs&amp;nbsp;5,&amp;nbsp;65lbs&amp;nbsp;5,&amp;nbsp;75lbs&amp;nbsp;5,&amp;nbsp;85lbs&amp;nbsp;5&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;4/21 금&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;row 5km&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;3R 6 Power snatch(75lbs), 15 burpee over the bar, 50 double under&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;bench press 45lbs 10, 55lbs 6, 65lbs 5, 75lbs 5, 85lbs 5, 95lbs 5&lt;br /&gt;&lt;br /&gt;4/24 월&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;30-20-10 hand release push up, dumbbell lateral burpee, dumbbell dual front squat(30lbs)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;squat 45lbs 5, 75lbs 5, 105lbs 5, 125lbs 5, 145lbs 3, 165lbs 3&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;assert bike 10km&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;핸드릴리즈푸쉬업이 생각보다 더 힘들었음&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;4/25 화&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;4R 25 wall ball(12lbs), 8 hang power clean(95lbs), 20 cal row&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;ohp 45lbs 5, 55lbs 5, 65lbs 5, 75lbs 3, 85lbs 3&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;행파클 115는 아직 힘들다. 95는 8개 한방에 갈 수 있음&lt;br /&gt;&lt;br /&gt;4/27 목&lt;br /&gt;deadlift 115lbs 1, 165lbs 1, 195lbs 1, 225lbs 1, 255lbs 1, 125lbs 6x10&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;데드 1rm 갱신ㅎㅎ&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;5/1 월&lt;br /&gt;front squat 45lbs 10, 95lbs 8, 135lbs 3, 165lbs 1, 185lbs 1, 205lbs 1, 135lbs 5, 155lbs 4, 165lbs 4x2 &lt;br /&gt;squat 155lbs 6, 175lbs 6, 195lbs 2&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;5R &lt;span&gt;2:00 On / 1:00 Off &lt;/span&gt;&lt;span&gt;75 Double under, &lt;/span&gt;&lt;span&gt;Max Pull up in remaining time&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;5/2 화&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;4R 15 cal row, 8 shoulder to overhead(75lbs)&lt;br /&gt;&lt;br /&gt;5/4 목&lt;br /&gt;bench press 45lbs 10, 75lbs 3, 105lbs 1, 135lbs 실패, 75lbs 5x5&lt;br /&gt;&lt;br /&gt;5/8 월&lt;br /&gt;18-15-12-9-6 overhead squat(45lbs), burpee over bar&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;손목 아파서 굉장히 가볍게 함&lt;br /&gt;&lt;br /&gt;5/9 화&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;50 push press(75 lbs), 100 box jump, 150 double under&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;5/16 화&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;squat 45lbs 5, 75lbs 5, 105lbs 5, 125lbs 3, 135lbs 5, 165lbs 5, 185lbs 5&lt;br /&gt;21-18-15-9-6-3 overhead squat(65lbs), push up / 30 double under between rounds&lt;br /&gt;&lt;br /&gt;오버헤드스쿼트 되게 어렵다. 등으로 딱 안받으면 손목 너무 아픔&lt;br /&gt;&lt;br /&gt;5/17 수&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;ohp 45lbs 5x2, 55lbs 5, 65lbs 5, 75lbs 5, 85lbs 5&lt;br /&gt;4R 30 air squats, 19 power clean(95lbs), 7 strict pull up(purple), 500m row&lt;br /&gt;&lt;br /&gt;5/18 목&lt;br /&gt;bench press 45lbs 5, 55lbs 5, 65lbs 5, 75lbs 5, 85lbs 5, 95lbs 5&lt;br /&gt;deadlift 95lbs 5, 115lbs 5, 135lbs 5, 155lbs 5, 175lbs 5, 195lbs 5&lt;br /&gt;60 wall ball shot(12lbs), 45 box jumps, 30 clusters(85lbs)&lt;br /&gt;&lt;br /&gt;5/22 월&lt;br /&gt;squat 45lbs 10, 75lbs 5, 105lbs 5, 125lbs 5, 155lbs 3, 175lbs 3, 195lbs 3&lt;br /&gt;bench press 45lbs 10, 55lbs 5, 65lbs 5, 75lbs 3, 95lbs 3, 105lbs 3&lt;br /&gt;21cal row, 15 knee raise, 9 power clean(115lbs)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;토투바 넘나 어렵&lt;br /&gt;&lt;br /&gt;5/23 화&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;ohp 45lbs 10, 75lbs 3, 95lbs 1, 115lbs 1, 65lbs 3, 75lbs 3, 85lbs 3&lt;br /&gt;EMOM 7R 10 pogo burpee, 15 wall ball shot(12lbs), 12cal row, 10 dumbbell snatch(40lbs), 1 min rest&lt;br /&gt;&lt;br /&gt;ohp 1rm을 갱신했는데, 그와 별개로 좀 급하게 무게를 올려서 전거근? 광배근? 살짝 다친듯 복압 잘 줘야됨 그리고 EMOM 너무 힘들었음..&lt;br /&gt;&lt;br /&gt;5/30 화&lt;br /&gt;bench press 45lbs 10, 75lbs 3, 95lbs 2, 115lbs 1, 135lbs 1, 75lbs 3, 95lbs 3, 105lbs 3&lt;br /&gt;4R+31 30 double under, 10 thruster(75 lbs), 15 push up&lt;br /&gt;&lt;br /&gt;6/1 목&lt;br /&gt;squat 75lbs 5, 105lbs 5, 125lbs 5, 165lbs 5, 185lbs 3, 205lbs 1&lt;br /&gt;28 box jump over, 10R 5 handstand push up(2mats), 27 double under, 5 power clean(95lbs)&lt;br /&gt;&lt;br /&gt;6/5 월&lt;br /&gt;ohp 45lbs 10, 55lbs 5, 65lbs 5, 75lbs 5, 85lbs 3, 95lbs 2&lt;br /&gt;bench press 45lbs 10, 55lbs 5, 65lbs 5, 75lbs 5, 85lbs 5, 95lbs 3, 105lbs 2&lt;br /&gt;21-15-9 cluster(75lbs), box jump then 80 cal row&lt;br /&gt;&lt;br /&gt;6/6 화&lt;br /&gt;deadlift 45lbs 10, 115lbs 3, 185lbs 1, 235lbs 1, 275 x, 265 x, 175lbs 5, 195lbs 3, 215lbs 1&lt;br /&gt;&lt;br /&gt;6/9 금&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;100 double under, 40 knee to chest, 60 jumping squat, 20 burpee box jump over&lt;br /&gt;bench press 45lbs 5, 55lbs 5, 65lbs 5, 75lbs 5, 85lbs 5, 95lbs 3, 105lbs 3&lt;br /&gt;&lt;br /&gt;6/12 월&lt;br /&gt;3R 10 front squat(95lbs), 30/25/15 russian kettlebell swing(12kg) / 3R 20 goblet squat, 30/30/25 air squat&lt;br /&gt;assert bike 7500m&lt;br /&gt;strict pull up 6/4/3/3/3&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;원래 스쿼트 스트렝스 하려고 했는데 와드 하고 나니 하체를 못쓰겠음&lt;br /&gt;&lt;br /&gt;6/13 화&lt;br /&gt;5R 3 wall walk, 15 deadlift(135lbs), 20 sit up&lt;br /&gt;ohp 45lbs 5, 55lbs 5, 65lbs 5, 75lbs 5, 85lbs 5, 95lbs 2&lt;br /&gt;&lt;br /&gt;6/16 금&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;6R 5 squat clean(95lbs), 10 front rack lunge, 40 double under&lt;br /&gt;deadlift 95lbs 5, 115lbs 5, 135lbs 5&lt;br /&gt;&lt;br /&gt;6/19 월&lt;br /&gt;25R 5 wall ball shot(14lbs), 3 push ups, 1 power clean(135lbs)&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;135lbs 파워클린 좀 감동인 부분&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;6/20 화&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;squat 45lbs 5, 75lbs 5, 105lbs 5, 125lbs 5, 145lbs 5, 165lbs 5, 185lbs 5&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;120 wall ball shot(12lbs), 80 dumbbell snatch(30lbs), 40 box jumps&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;오늘은 체감상 평소보다 더 힘들었달까,,&lt;br /&gt;&lt;br /&gt;6/21 수&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;5R 12 deadlift(75lbs), 9 hang power clean, 6 jerk&lt;br /&gt;ohp 45lbs 10, 55lbs 5, 65lbs 5, 75lbs 5, 85lbs 5&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;95로 할 수 있을줄 알았는데 jerk가 힘들었다. 75는 좀 많이 가벼웠다.&lt;br /&gt;&lt;br /&gt;6/27 월&lt;br /&gt;deadlift 45lbs 10, 95lbs 5, 115lbs 5, 135lbs 5, 155lbs 5, 175lbs 5, 195lbs 5&lt;br /&gt;bench press 45lbs 10, 55lbs 5, 65lbs 5, 75lbs 5, 85lbs 5, 95lbs 5, 105lbs 5&lt;br /&gt;2R 3 box muscle up, 6 power clean(95lbs), 9 push jerk&lt;br /&gt;&lt;br /&gt;와드 중간에 DNF하고 또 다음날 테니스엘보 느낌 있었음;;&lt;br /&gt;&lt;br /&gt;7/27 목&lt;br /&gt;2R 50 air squat, 10 burpee, 40 ab-mat sit up, 10 burpee, 30 walking lunge, 10 burpee, 20 cal row&lt;br /&gt;&lt;br /&gt;숨이 너무 찼다 오랜만에 해서 그런듯&lt;br /&gt;&lt;br /&gt;7/31 월&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;3R 1 min wallball(20lbs), sumo deadlift high pull(75lbs), box jump, push press, cal row&lt;br /&gt;squat 75lbs 5, 95lbs 5, 115lbs 5, 125lbs 5, 145lbs 5, 155lbs 5&lt;br /&gt;&lt;br /&gt;찾아보니 1년전에는 빈바로 했었음. 성장한걸로...?&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;8/28 월&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;4R 500m Row, 20 wall ball(12lbs), 14 db snatch. alt(30lbs)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;안하다 하니 너무 힘들었음ㅎㅎ;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;8/29 화&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;amrap 15min 3-6-9-12.. knee raise, overhead squat(45lbs), burpee over the bar&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;9/4 월&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;amrap 15min 6 power snatch(65lbs), 9 overhead squat, 12 box jump&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;deadlift 45lbs 5, 95lbs 5, 125lbs 5, 155lbs 5, 175lbs 5&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;9/5 화&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;4R 15 cal row, 10 clean and jerk(75lbs), 5 front squat&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;bench press 45lbs 10, 65lbs 5, 75lbs 5, 85lbs 5, 95lbs 5&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;9/6 수&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;5R 5 deadlift(155lbs), 10 pull up(purple band), 15 wall ball(12lbs)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;squat 75lbs 5, 95lbs 5, 115lbs 5, 125lbs 5, 135lbs 5, 155lbs 5&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;9/8 금&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;5R 10 power clean(95lbs), 10 hand release push up, 10 knee to chest&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;ohp 45lbs 5, 55lbs 5, 65lbs 5, 75lbs 5&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;pull up(purple) 5x5&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;토투바는 언제 하지.. 할로우에서 어깨를 누르는 느낌을 잘 모르겠음&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;9/11 월&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2R 15 thruster(75lbs), 15 burpee over the bar, max cal row&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;deadlift 45lbs 5, 75lbs 5, 105lbs 5, 125lbs 5, 135lbs 5, 155lbs 5, 175lbs 5&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;9/12 화&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1000m row, 80 wall ball(14lbs), 200 double under&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;45lbs 5, 55lbs 5, 65lbs 5, 75lbs 5, 85lbs 5, 95lbs 5&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;pull up 5x5(purple)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;와드때 숨 겁나 찼음&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;9/13 수&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;5R 10 hang squat clean(65lbs), 8 front squat, 8 push press&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;squat 75lbs 5, 95lbs 5, 115lbs 5, 135lbs 3, 155lbs 3, 175lbs 3&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;push press가 힘들어서 65lbs로 했음..ㅠ&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;9/14 목&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;5R 6 deadlift(155lbs), 12 box step up with kettlebell(16kg), 18 russian kettlebell swing&lt;br /&gt;ohp 45lbs 10, 55lbs 5, 65lbs 5, 75lbs 3, 85lbs 3, 95lbs 1&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;9/15 금&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;wall walk, double under 1/10 3/30 6/60 9/90 15/150&lt;br /&gt;&lt;br /&gt;9/21 목&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;5R 14 russian kettle bell swing(16kg), 20 wall ball(12lbs), 30 air squat&lt;br /&gt;deadlift 75lbs 5, 105lbs 5, 125lbs 5, 145lbs 3, 165lbs 3, 195lbs 3&lt;br /&gt;&lt;br /&gt;9/23 토&lt;br /&gt;bench press 45lbs 12, 55lbs 12, 65lbs 5, 75lbs 5, 85lbs 5, 95lbs 5, 105lbs 3&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;9/25 월&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;50 double under, 50 thruster(65lbs), 50 cal row&lt;br /&gt;squat 45lbs 5, 75lbs 5, 95lbs 5, 115lbs 5, 145lbs 3, 165lbs 3, 185lbs 1, 185lbs 1&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;9/26 화&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;5R 30sec wall sit, 12 burpee over the bar, 6 clean(95lbs)&lt;br /&gt;ohp 45lbs 5, 55lbs 5, 65lbs 5, 75lbs 3, 85lbs 3&lt;br /&gt;&lt;br /&gt;ohp 95lbs 못들음&lt;br /&gt;&lt;br /&gt;10/4 수&lt;br /&gt;5R 30 front lunge, 5 power snatch(65lbs), 10 overhead squat&lt;br /&gt;deadlift 75lbs 5, 105lbs 5, 125lbs 5, 155lbs 5, 185lbs 3, 205lbs 1, 225lbs 1, 245lbs x&lt;/p&gt;</description>
      <category>일상/ETC</category>
      <author>BaaaaaaaaaaaaaaaaaaaaaaarkingDog</author>
      <guid isPermaLink="true">https://baaaaaaaaaaaaaaaaaaaaaaarkingdog.tistory.com/1051</guid>
      <comments>https://baaaaaaaaaaaaaaaaaaaaaaarkingdog.tistory.com/1051#entry1051comment</comments>
      <pubDate>Sun, 17 Apr 2022 15:45:45 +0900</pubDate>
    </item>
    <item>
      <title>[LINE CTF 2022] lazy_stek</title>
      <link>https://baaaaaaaaaaaaaaaaaaaaaaarkingdog.tistory.com/1049</link>
      <description>&lt;p&gt;Vulnerability is quite simple(nonce reuse in GCM mode) but I was struggled with TCP packet structure. I am newbie in network...&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;I confused that GCM mode is affected on Application data but it wasn't. It is related with PSK Identity field(I realized this by searching aa aa aa aa / bb bb bb bb hex data)&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;645&quot; data-origin-height=&quot;565&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/TDlhk/btrxu9D8QCR/mCkSfWuxGgPFFUJXuBIXMk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/TDlhk/btrxu9D8QCR/mCkSfWuxGgPFFUJXuBIXMk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/TDlhk/btrxu9D8QCR/mCkSfWuxGgPFFUJXuBIXMk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FTDlhk%2Fbtrxu9D8QCR%2FmCkSfWuxGgPFFUJXuBIXMk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;645&quot; height=&quot;565&quot; data-origin-width=&quot;645&quot; data-origin-height=&quot;565&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p&gt;&amp;nbsp;There are three PSK Identity field data, and IV is collide.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;739&quot; data-origin-height=&quot;824&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cPJQ5A/btrxwzWTKtE/1PxfGp1y6dtXCFEgWHk8w1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cPJQ5A/btrxwzWTKtE/1PxfGp1y6dtXCFEgWHk8w1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cPJQ5A/btrxwzWTKtE/1PxfGp1y6dtXCFEgWHk8w1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcPJQ5A%2FbtrxwzWTKtE%2F1PxfGp1y6dtXCFEgWHk8w1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;739&quot; height=&quot;824&quot; data-origin-width=&quot;739&quot; data-origin-height=&quot;824&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p&gt;First two data are encrypted using $key0$, last one is encrypted using $key1$. It is known that single nonce collision in GCM break downs all. Moreover, $H = AES_K(0^n)$ is revealed by solving univariate equation in GF field. Since $key1 = AES_{key0}(0^n) = H$, everything is clear. I know that below code is ugly and I will refactor someday &amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;b&gt;solver.sage&lt;/b&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1648358625850&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;from binascii import unhexlify, hexlify
import hashlib
from Crypto.Cipher import AES

def slice_and_pad(b_str, bsize=16):
    rem = (bsize - len(b_str) % bsize) % bsize
    b_str += b&quot;\x00&quot; * rem
    return [bytearray(b_str[k:k+bsize]) for k in range(0, len(b_str), bsize)]


def unhex_blocks(h_str, bsize=16):
    h_str = unhexlify(h_str)
    return slice_and_pad(h_str, bsize)

def xor(a, b):
    assert(len(a) == len(b))
    return bytearray([a[i] ^^ b[i] for i in range((len(a)))])

def byte_to_bin(byte):
    b = bin(byte)[2:]
    return &quot;0&quot; * (8 - len(b)) + b

def block_to_bin(block):
    assert(len(block) == 16)
    b = &quot;&quot;
    for byte in block:
        b += byte_to_bin(byte)
    return b

def bytes_to_poly(block, a):
    f = 0
    for e, bit in enumerate(block_to_bin(block)):
        f += int(bit) * a**e
    return f

def poly_to_int(poly):
    a = 0
    for i, bit in enumerate(poly._vector_()):
        a |= int(bit) &amp;lt;&amp;lt; (127 - i)
    return a

def poly_to_hex(poly):
    return (hex(poly_to_int(poly))[2:])

def GCM_poly(COEF, L_p, C_p, A_p):
    return COEF + L_p * X + sum(C_p[i] * X**(len(C_p)+1-i) for i in range(len(C_p))) + sum(A_p[i] * X**(len(C_p)+len(A_p)+1-i) for i in range(len(A_p)))

# C &amp;amp; AAD are hexstring(i.e. &quot;11223344&quot;)
def forge_message(enc_J0_p, H_p, C, AAD, A_p):
    L = unhex_blocks(hex(((int)(160 &amp;lt;&amp;lt; 64) | (len(C)*4)))[2:].zfill(32))[0]
    L_p = bytes_to_poly(L, a)
    C_block = unhex_blocks(C)
    C_p = [bytes_to_poly(elem, a) for elem in C_block]
    T = poly_to_hex(GCM_poly(enc_J0_p, L_p, C_p, A_p)(H_p))
    msg = AAD + C + T
    return msg

# packet 4
dat1 = '256f6e3b40c2c006f26dbe24b70c6ed6e875cec70f64aac0de67af2caaaaaaaa450abecfee723cdbe4393bbcf56add91e283615eaa6a5899906a138ce3dbe632ab778328029499c12eceefa0589945f7f3801748be3daa06ace2e682a77649da535f7235aa7ecb60bf0e3d6b7c1012e192411e29e6494c2fa05ce2c5d08d4698a05ffb5fa9ad2b2550737cea3b19ccacfdd93e7d3c3f6e641d5f8793b17261047b160c9acaf891577ef7'
C1 = unhex_blocks(dat1[64:-32])
T1 = unhex_blocks(dat1[-32:])
A1 = unhex_blocks(dat1[:64])
L1 = unhex_blocks(hex(((int)(256 &amp;lt;&amp;lt; 64) | 976))[2:].zfill(32))

# packet 10
dat2 = '256f6e3b40c2c006f26dbe24b70c6ed6e875cec70f64aac0de67af2caaaaaaaa450abecfee723cdbe4393bbce26a50c35bd4b250c5395150b62c27d76e20535dea6a129d08c1c31e89475b79d36e45f7f3801748be3daa06ace2e682a77649da535f7235aa7ecb60bf0e3d6b7c1012e192411e29e6494c2fa05ce2c5d08d4698a05ffb5fa9ad2b2550737cea3b19ccacfdd93e7d3c3f6e641d5f1f668e1af6844a40e4cbdb6132cbd395'
C2 = unhex_blocks(dat2[64:-32])
T2 = unhex_blocks(dat2[-32:])
A2 = unhex_blocks(dat2[:64])
L2 = unhex_blocks(hex(((int)(256 &amp;lt;&amp;lt; 64) | 976))[2:].zfill(32))

F, a = GF(2**128, name=&quot;a&quot;).objgen()
R, X = PolynomialRing(F, name=&quot;X&quot;).objgen()
    
A1_p = [bytes_to_poly(elem, a) for elem in A1]
C1_p = [bytes_to_poly(elem, a) for elem in C1]
T1_p = [bytes_to_poly(elem, a) for elem in T1]
L1_p = [bytes_to_poly(elem, a) for elem in L1]

A2_p = [bytes_to_poly(elem, a) for elem in A2]
C2_p = [bytes_to_poly(elem, a) for elem in C2]
T2_p = [bytes_to_poly(elem, a) for elem in T2]
L2_p = [bytes_to_poly(elem, a) for elem in L2]

print(L1_p)

f1 = GCM_poly(T1_p[0], L1_p[0], C1_p, A1_p)
f2 = GCM_poly(T2_p[0], L2_p[0], C2_p, A2_p)

# 1. Recover H from iv reuse
p1 = f1 + f2
# only one candidate
for root, _ in p1.roots():
    H_p = root
    if H_p == 0: continue
    H = poly_to_hex(H_p)
    print(&quot;H&quot;, H)
    break

# 2. Recover key1
key1 = hashlib.sha256(bytes.fromhex(H)).digest()

# 3. Extract keyname, aeskey
dat3 = 'ffd08593ad673b9005296a50f603af28c336d16a10aac82969a59560bbbbbbbb6fe550ba6db4b6a2af74f6f0454d82d959daa387f694685dec4c1ff7c36e40d3b9fe6e4fd41596035a594f8b599b89c47c84aa66d6d63ef3999de5041f0c3b7598b1811012399575a0c442c1c364f669ecf7fd5dfbb06bc37fd830c03e3dde20c98bc747d74d0ac196936f364c2e81338fca4bdb193d52e19f23295fc9e7546288a7464baa258fcd5542'
C = bytes.fromhex(dat3[64:-32])
T = bytes.fromhex(dat3[-32:])
AAD = bytes.fromhex(dat3[:64])
iv = bytes.fromhex(dat3[32:32+24])
chk = hashlib.sha512(key1).digest()
keyname = chk[:16]
aeskey = chk[16:32]
assert(keyname == AAD[:16])

# 4. decrypt
cipher = AES.new(aeskey, AES.MODE_GCM, iv)
cipher.update(AAD)
plain_data = cipher.decrypt_and_verify(C, T)
print(plain_data)&lt;/code&gt;&lt;/pre&gt;</description>
      <category>CTF/Crypto</category>
      <author>BaaaaaaaaaaaaaaaaaaaaaaarkingDog</author>
      <guid isPermaLink="true">https://baaaaaaaaaaaaaaaaaaaaaaarkingdog.tistory.com/1049</guid>
      <comments>https://baaaaaaaaaaaaaaaaaaaaaaarkingdog.tistory.com/1049#entry1049comment</comments>
      <pubDate>Sun, 27 Mar 2022 14:25:39 +0900</pubDate>
    </item>
  </channel>
</rss>