공통 부분 문자열(백준_5582)

2023. 2. 7. 16:24·BackEnd/알고리즘 공부

https://www.acmicpc.net/problem/5582

 

5582번: 공통 부분 문자열

두 문자열이 주어졌을 때, 두 문자열에 모두 포함된 가장 긴 공통 부분 문자열을 찾는 프로그램을 작성하시오. 어떤 문자열 s의 부분 문자열 t란, s에 t가 연속으로 나타나는 것을 말한다. 예를 들

www.acmicpc.net

문제 설명

2개의 문자열이 주어지면 2개의 문자열에 모두 포함 된  부분문자열 중 가장 긴 것의 길이를 출력하는 것이다.

ABRACADABRA와 ECADADABRBCRDARA의 공통 부분 문자열은 CA, CADA, ADABR이 존재한다. 이 중 제일 긴 문자열의 길이는 5이기 때문에 답은 5이다.

 

문제에 대한 아이디어 

공통의 부분 문자열을 찾는 알고리즘이다. 이 알고리즘 가장 유명한 것은 LCS 알고리즘이다. 

LCS는 주로 최장 공통 부분수열을 말한다.  최장 공통 문자열을 말하기도 한다.

최장 공통 부분수열이 최장 공통 문자열 보다 찾기가 어렵다. 

출처 : 그림으로 알아보는 LCS 알고리즘

이 문제는 이중 최장 공통 문자열을 찾는 문제이다.

 

다이나믹 프로그래밍을 이용하여 문제풀기

1. 2차원 배열 만들기

2개의 문자열 길이 만큼 2차원 배열을 생성한다.

 

2. 점화식을 사용하여 문제 풀어나가기

 

G가 있는 첫번째 행부터 생각해보자. G와 A를 비교해보면 같은 것이 없다. 그러므로 0 이다.

G와 B를 비교해도 같은 것이 없다.  G와 B를 비교하는 것은 생각해보면 G와 AB를 비교하는 것이다. 이렇게 모든 행과 열을 비교한다.

이제 2번째 행을 보면 B와 A를 비교하면 0, B와 B는 같기 때문에 1로 해야한다. 하지만 그전에 대각선 왼쪽 위의 값을 확인해야한다. 

이 부분을 알아보기 위해 3번 째 행에 C와 C를 비교한 부분을 보겠다. 둘은 같으므로 +1을 해야한다. 대각선 왼쪽 위를 보면 AB와 GB를 비교한 부분이다. AB와 GB의 비교는 같은 부분 문자열이 B가 1개 존재한다. 그러므로 GBC와 ABC 비교하는 부분은 AB와 GB를 비교한 것 + 1을 해주는 것이다.

  • D[ i ][ j ] = D[ i + 1 ][ j + 1 ] + 1인 것이다.

for(int i = 0; i< str1.length(); ++i){
    for(int j = 0; j<str2.length(); ++j){
        if(str1.charAt(i) == str2.charAt(j)){
            pro[i+1][j+1] = pro[i][j] + 1;
            max = Math.max(max, pro[i+1][j+1]);
        }
    }
}

 

최장 공통 부분수열은 어떻게 구할까?

  1. 문자열A, 문자열B의 한글자씩 비교하기
  2. 두 문자가 다르면 D[ i -1 ][ j ] 와 D[ i ][ j - 1 ] 중 큰 값을 가져온다.
  3. 두 문자가 같다면 D[ i - 1][ j - 1 ] 값의 + 1 
  4. 이 행동을 반복한다.

 

2번을 왜하냐면 부분수열은 연속된 값이 아니기 때문이다. 

색칠된 부분은 보면 저기는 GBC와 AB를 비교하는 것이다. 공통 부분 문자열은 같은 연속된 것이 없었지만 공통 부분 수열은 공통된 값인 B가 존재한다. 그래서 저번 비교할 때 공통 수열이 존재하면 계속 값을 가져가는 것이다!!

for(int i = 0; i< str1.length(); ++i){
    for(int j = 0; j<str2.length(); ++j){
        if(str1.charAt(i) == str2.charAt(j)){
            pro[i+1][j+1] = pro[i][j] + 1;
        }else{
            pro[i+1][j+1] = Math.max(pro[i][j+1], pro[i+1][j]);
        }
        max = Math.max(max, pro[i+1][j+1]);
    }
}

최장 공통 부분 수열이 어떤 것인지 찾는 방법도 있다.

 

구현

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;

public class 백준_5582 {
    public static void main(String []args) throws IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        String str1 = br.readLine();
        String str2 = br.readLine();
        int [][] pro = new int[str1.length()+1][str2.length()+1];
        int max = 0;
        for(int i = 0; i< str1.length(); ++i){
            for(int j = 0; j<str2.length(); ++j){
                if(str1.charAt(i) == str2.charAt(j)){
                    pro[i+1][j+1] = pro[i][j] + 1;
                }else{
                    pro[i+1][j+1] = Math.max(pro[i][j+1], pro[i+1][j]);
                }
                max = Math.max(max, pro[i+1][j+1]);
            }
        }
        System.out.println(max);
    }
}

https://github.com/Heron-Woong/CodingTest_Practice/commit/bc08bf0deb16b3028dadf79eea21ef8bd9cd30d5

 

백준_5582, 공통 부분 문자열 · Heron-Woong/CodingTest_Practice@bc08bf0

Showing 1 changed file with 22 additions and 0 deletions.

github.com

 

문자열과 관련된 알고리즘!!
1. KMP 알고리즘 : 2개의 문자열이 주어지면 하나의 문자열에 다른 문자열이 존재하는지 검사한다.
2. Boyer-Moore 알고리즘 
3. 편집거리 알고리즘
4. LCS

 

'BackEnd > 알고리즘 공부' 카테고리의 다른 글

가장 큰 정사각형  (0) 2023.02.10
조합과 순열 구현해보기  (0) 2023.02.09
사전(백준_1256)  (0) 2023.02.06
빵집(백준_3109)  (1) 2023.02.05
최소 공통 조상 구하기(LCA)  (0) 2023.02.04
'BackEnd/알고리즘 공부' 카테고리의 다른 글
  • 가장 큰 정사각형
  • 조합과 순열 구현해보기
  • 사전(백준_1256)
  • 빵집(백준_3109)
인프라 감자
인프라 감자
  • 인프라 감자
    삶은 인프라
    인프라 감자
  • 전체
    오늘
    어제
    • 분류 전체보기 (243)
      • 클라우드&인프라 (28)
        • 인프라 공부 (4)
        • AWS 구조와 서비스 (18)
        • 클라우드 공부 (4)
        • Terraform (2)
      • AWS Cloud School (13)
        • project (5)
        • Linux, Network (6)
        • Docker (2)
      • BackEnd (162)
        • JAVA 공부 (15)
        • 알고리즘 공부 (71)
        • MySQL 문제 풀기 (8)
        • 스프링 핵심 원리 - 기본편 (18)
        • 스프링 MVC 1편 (4)
        • 자바 ORM 표준 JPA 프로그래밍 (21)
        • 실전! 스프링 부트와 JPA 활용1 (8)
        • 실전! 스프링 부트와 JPA 활용2 (5)
        • 스프링 데이터 JPA (8)
        • Querydsl (4)
      • 혼자하는 프로젝트 (32)
        • 배달의 민족 클론코딩 (7)
        • 나만의 프로젝트 (10)
        • 스프링 부트로 구현한 웹 (15)
  • 블로그 메뉴

    • 홈
    • 태그
    • 방명록
  • 링크

    • Email
    • GitHub
  • 공지사항

  • 인기 글

  • 태그

    프로그래머스
    조합
    VPN
    스프링 핵심 원리-기본편
    정렬
    linux
    중첩 선언
    디팬스 게임
    자바
    백트래킹
    자동 배포
    다이나믹 프로그래밍
    완전탐색
    이것이 자바다
    dp
    상속
    querydsl
    쿼드 압축
    네트워크 기본 용어
    유니온 파인드
  • 최근 댓글

  • 최근 글

  • hELLO· Designed By정상우.v4.10.3
인프라 감자
공통 부분 문자열(백준_5582)
상단으로

티스토리툴바