백준 5582 - 공통 부분 문자열

Updated:

Java

5582 번 - 공통 부분 문자열

문제

두 문자열이 주어졌을 때, 두 문자열에 모두 포함된 가장 긴 공통 부분 문자열을 찾는 프로그램을 작성하시오.

어떤 문자열 s의 부분 문자열 t란, s에 t가 연속으로 나타나는 것을 말한다. 예를 들어, 문자열 ABRACADABRA의 부분 문자열은 ABRA, RAC, D, ACADABRA, ABRACADABRA, 빈 문자열 등이다. 하지만, ABRC, RAA, BA, K는 부분 문자열이 아니다.

두 문자열 ABRACADABRA와 ECADADABRBCRDARA의 공통 부분 문자열은 CA, CADA, ADABR, 빈 문자열 등이 있다. 이 중에서 가장 긴 공통 부분 문자열은 ADABR이며, 길이는 5이다. 또, 두 문자열이 UPWJCIRUCAXIIRGL와 SBQNYBSBZDFNEV인 경우에는 가장 긴 공통 부분 문자열은 빈 문자열이다.

접근 방법

구현

코드

/*
5582번 - 공통 부분 문자열
https://www.acmicpc.net/problem/5582
*/

import java.util.*;
import java.io.*;

public class Main {
	static int result = 0;
	public static void main(String[] args) throws IOException {
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
    	StringTokenizer stk;
    	String a = br.readLine();
    	String b = br.readLine();
    	
    	int alen = a.length(), blen = b.length(); 
    	int[][] dp = new int[alen][blen];		// 각 문자열의 길이만큼 2차원 배열을 만든다.
    	
    	for(int i = 0; i < alen; i++) {
    		for(int j = 0; j < blen; j++) {
    			if(a.charAt(i) == b.charAt(j)) {
    				if(i == 0 || j == 0) {		// i, j 중 둘 중 하나라도 0이라면, i-1 or j-1이 -1이 되므로 IndexExecption이 되므로 방지
    					dp[i][j] = 1;
    				}
    				else {
    					dp[i][j] = dp[i-1][j-1] + 1;	// 현재 문자가 같으면, 직전 문자까지 동일한 두 부분 문자열 길이에 대해 1을 증가한다
    				}
    				result = Math.max(result, dp[i][j]);	// 문자열 길이 최대값
    			}
    		}
    	}
    	
    	System.out.println(result);
    	br.close();
	}
	static int stoi(String str) {
    	return Integer.parseInt(str);
    }
}
Sliding Window로 실패한 코드
/*
5582번 - 공통 부분 문자열
https://www.acmicpc.net/problem/5582
*/

import java.util.*;
import java.io.*;

public class Main {
	static int result;
	public static void main(String[] args) throws IOException {
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
    	String a = br.readLine();
    	String b = br.readLine();
    	
    	if(a.length() > b.length()) {
    		String temp = a;
    		a = b;
    		b = temp;
    	}
    	
    	String str;
    	int size = a.length();
    	int l = 0, r = 0;	// 왼쪽 선, 오른쪽 선
    	int pm = 1;			// 1씩 늘려갈지, -1로 줄여 나갈시
    	
    	while(true) {
    		r += pm;		// 오른쪽 선을 좌,우로 이동한다.
    		if(r > size) {	// 만약 오른쪽 선이 size를 넘어가면, 다시 왼쪽으로 줄여나간다
    			pm = -1;
    			l++;
    			if(l == size)
    				break;
    			continue;
    		}
    		if(r == l) {	// 만약 오른족 선이 left와 마주치면, 다시 오른쪽으로 늘려나간다.
    			pm = 1;
    			l++;
    			r++;
    			if(l == size)
    				break;
    			continue;
    		}
    		str = a.substring(l,r); // sliding window(l,r)로 문자열을 자른다.
			if(b.contains(str)) {	// 대상 문자열에 포함되어 있으면 길이 최대값
				result = Math.max(r - l, result);
			}
    	}
    	System.out.println(result);
    	br.close();
	}
}

총평

난이도

⭐★★★★

후기

이전에도 접했던 문제이기 때문에 쉽게 해결 가능했다.

개선할 점