LCS algorithm์ ๋ ๊ฐ์ง๋ก ํด์์ด ๋๋ค. Longest Common Subsequence์ Longest Common Substring์ด๋ค. Subsequence์ ๋ฌธ์์ด์ ๋ถ๋ถ ๋ฌธ์์ด๋ค์ ์กฐํฉ์ด ๊ฐ์ฅ ๊ธธ๊ฒ ๊ฐ์ ๋ ๋ฌธ์์ด์ ๊ณตํต ๋ถ๋ถ์ ์ด์ผ๊ธฐ ํ๋ค. Substring์ ๋ฌธ์์ด์ ํ ๋ถ๋ถ ๋ฌธ์์ด์ด ๊ฐ์ฅ ๊ธธ๊ฒ ๊ฐ์ ๋ ๋ฌธ์์ด์ ๊ณตํต ๋ถ๋ถ์ ์ด์ผ๊ธฐํ๋ค. ์ผ๋ฐ์ ์ผ๋ก๋ subsequence๋ฅผ ์ด์ผ๊ธฐํ๋ค.
Step 0. ๋ฌธ์์ด A์ ๋ฌธ์์ด B์ ๊ธธ์ด์ ๋ฐ๋ผ LCS ๋ฐฐ์ด์ ์์ฑ
private final String strA;
private final String strB;
private int[][] lcs;
private void initializeLCSArray() {
lcs = new int[strA.length() + 1][strB.length() + 1];
}
Step 1. ๋ฌธ์์ด A์ ๋ฌธ์์ด B๋ฅผ ์์์๋ถํฐ ํ ๋ฌธ์์ฉ ๋น๊ต
Step 1-1. ๋ ๋ฌธ์๊ฐ ๋ค๋ฅด๋ค๋ฉด LCS[i - 1][j], LCS{i][j - 1] ์ค ํฐ๊ฐ์ ์ ์ฅ
Step 1-2. ๋ ๋ฌธ์๊ฐ ๊ฐ๋ค๋ฉด LCS[i - 1][j - 1] + 1 ์ ์ฅ
private void compareChars() {
for (int i = 1; i <= strA.length(); i++)
for (int j = 1; j <= strB.length(); j++)
lcs[i][j] = strA.charAt(i - 1) == strB.charAt(j - 1) ?
lcs[i - 1][j - 1] + 1 :
Math.max(lcs[i - 1][j], lcs[i][j - 1]);
}
Step 2. ๊ณตํต ๋ถ๋ถ ๋ฌธ์์ด ์ฐพ๊ธฐ (0์ผ๋ก ์ด๋ํ๋ฉด ์ข ๋ฃ)
Step 2-1. LCS ๋ฐฐ์ด์ ๋ง์ง๋ง ๊ฐ๋ถํฐ ํ์
Step 2-2. LCS[i - 1][j]์ LCS[i][j _ 1] ์ค ๊ฐ์ ๊ฐ์ด ์์ผ๋ฉด ํด๋น ๊ฐ์ผ๋ก ์ด๋
Step 2-3. ๊ฐ์๊ฐ์ด ์์ผ๋ฉด ๋ฌธ์๋ฅผ ๊ณตํต ๋ถ๋ถ์ ์ถ๊ฐํ๊ณ i - 1, j - 1 ์ด๋
private String findCommonString() {
StringBuilder builder = new StringBuilder();
int i = strA.length();
int j = strB.length();
while (lcs[i][j] != 0) {
if (lcs[i - 1][j] == lcs[i][j]) i--;
else if (lcs[i][j - 1] == lcs[i][j]) j--;
else {
builder.append(strA.charAt(i - 1));
i--;
j--;
}
}
return builder.reverse().toString();
}
LCS(Substring)์ LCS(Subsequence)์์ ๋ ๋ฌธ์๊ฐ ๋ค๋ฅผ ๋๋ง 0์ผ๋ก ์ ์ฅํ๋ฉด ๋๋ค.
์ถ๊ฐ๋ก substring์ ์ต์ฅ ๊ธธ์ด ํ์์ ํ๋ฉด์ ๋์์ ์ต์ฅ ๊ณตํต ๋ฌธ์์ด์ ๊ตฌํ ์ ์๋ค.
private String compareSubstringChars() {
String common = "";
for (int i = 1; i <= strI.length(); i++) {
for (int j = 1; j <= strJ.length(); j++) {
if (strI.charAt(i - 1) == strJ.charAt(j - 1)) {
lcs[i][j] = lcs[i - 1][j - 1] + 1;
String string = strI.substring(i - lcs[i][j], i);
if (common.length() < string.length()) common = string;
}
}
}
return common;
}
public class LCS {
private final String strA;
private final String strB;
private int[][] lcs;
public LCS(String strA, String strB) {
this.strA = strA;
this.strB = strB;
}
public String runSubsequence() {
initializeLCSArray();
compareChars();
return findCommonString();
}
private void initializeLCSArray() {
lcs = new int[strA.length() + 1][strB.length() + 1];
}
private void compareChars() {
for (int i = 1; i <= strA.length(); i++)
for (int j = 1; j <= strB.length(); j++)
lcs[i][j] = strA.charAt(i - 1) == strB.charAt(j - 1) ?
lcs[i - 1][j - 1] + 1 :
Math.max(lcs[i - 1][j], lcs[i][j - 1]);
}
private String findCommonString() {
StringBuilder builder = new StringBuilder();
int i = strA.length();
int j = strB.length();
while (lcs[i][j] != 0) {
if (lcs[i - 1][j] == lcs[i][j]) i--;
else if (lcs[i][j - 1] == lcs[i][j]) j--;
else {
builder.append(strA.charAt(i - 1));
i--;
j--;
}
}
return builder.reverse().toString();
}
}