[프로그래머스] 42893. 매칭 점수
문제 링크
풀이 과정
문자열을 파싱해 원하는 부분만을 뽑아낼 수 있는 지를 확인하는 문제입니다.
<meta>, <a>, <body> 태그 내부에서의 문자열 검색은 모두 indexOf
메소드를 사용했습니다.
static void setUrl(Info[] infos, int index, String page) {
String search = "<meta property=\"og:url\" content=\"";
int url_start_idx = page.indexOf(search) + search.length();
int url_end_idx = url_start_idx + page.substring(url_start_idx).indexOf("\"/>");
String url = page.substring(url_start_idx, url_end_idx);
infos[index].url = url;
}
위의 setUrl 메소드는 태그 내의 content 속성 값을 뽑아내어 배열 요소에 저장하는 과정을 거칩니다. 태그의 포맷으로 search
라는 이름의 변수를 하나 지정한 뒤, 이 문자열이 끝나는 지점의 인덱스를 구합니다. 해당 인덱스가 url의 시작 인덱스가 되며, substring 과 indexOf 메소드를 통해 끝나는 지점의 인덱스도 구할 수 있습니다.
static void setExternalLinks(Info[] infos, int index, String page) {
ArrayList<String> externalLinks = new ArrayList<>();
String search = "<a href=\"";
String tmp = page;
while (tmp.indexOf(search) != -1) {
int a_start_idx = tmp.indexOf(search) + search.length();
int a_end_idx = a_start_idx + tmp.substring(a_start_idx).indexOf("\">");
String externalLink = tmp.substring(a_start_idx, a_end_idx);
externalLinks.add(externalLink);
tmp = tmp.substring(a_end_idx);
}
infos[index].externalLinks = externalLinks;
infos[index].externalLinkCnt = externalLinks.size();
}
외부 링크는 <a> 태그로 이루어져 있습니다. setExternalLinks 메소드는 <body> 태그 내에 존재하는 <a> 태그들을 검색합니다. 하나 이상의 여러 <a> 태그가 존재할 수 있으므로, while 문을 통해 모두 검색하도록 합니다. 외부 링크 주소를 잘라내어 배열 요소 객체 내의 ArrayList에 추가하고, 그 개수도 저장합니다.
static void setBasicScore(Info[] infos, int index, String page, String word) {
String search = "<body>";
int body_start_idx = page.indexOf(search) + search.length();
int body_end_idx = body_start_idx + page.substring(body_start_idx).indexOf("</body>");
String body = page.substring(body_start_idx, body_end_idx).toUpperCase();
body = body.toUpperCase();
word = word.toUpperCase();
int cnt = 0;
int find = body.indexOf(word);
while (find != -1) {
char prev = body.charAt(find - 1);
char next = body.charAt(find + word.length());
if (!Character.isLetter(prev) && !Character.isLetter(next)) {
cnt++;
}
find = body.indexOf(word, find + 1);
}
infos[index].basicScore = cnt;
}
setBasicScore
메소드는, <body> 태그 내부에 word 문자열과 매칭되는 단어들의 개수를 세어 저장하는 메소드입니다. 예를 들어, 검색어가 “aba” 인 경우, “abab abababa”는 단어 단위로 매칭되지 않으므로, 그 개수는 0이 됩니다. 이런 과정은 단어의 바로 전과 후가 알파벳인지를 확인하는 isLetter 메소드로 확인할 수 있습니다.
코드
import java.util.ArrayList;
import java.util.Arrays;
public class Main {
public static int solution(String word, String[] pages) {
int answer = 0;
Info[] infos = new Info[pages.length];
for (int i = 0; i < infos.length; i++) {
infos[i] = new Info(i);
}
for (int i = 0; i < pages.length; i++) {
String page = pages[i];
setUrl(infos, i, page);
setExternalLinks(infos, i, page);
setBasicScore(infos, i, page, word);
}
for (int i = 0; i < infos.length; i++) {
double total = 0;
for (int j = 0; j < infos.length; j++) {
if (i == j) continue;
if (infos[j].externalLinks.contains(infos[i].url)) {
total += (double) infos[j].basicScore / infos[j].externalLinkCnt;
}
}
infos[i].linkScore = total;
infos[i].matchingScore = infos[i].basicScore + infos[i].linkScore;
}
Arrays.sort(infos);
answer = infos[0].index;
return answer;
}
static void setUrl(Info[] infos, int index, String page) {
String search = "<meta property=\"og:url\" content=\"";
int url_start_idx = page.indexOf(search) + search.length();
int url_end_idx = url_start_idx + page.substring(url_start_idx).indexOf("\"/>");
String url = page.substring(url_start_idx, url_end_idx);
infos[index].url = url;
}
static void setExternalLinks(Info[] infos, int index, String page) {
ArrayList<String> externalLinks = new ArrayList<>();
String search = "<a href=\"";
String tmp = page;
while (tmp.indexOf(search) != -1) {
int a_start_idx = tmp.indexOf(search) + search.length();
int a_end_idx = a_start_idx + tmp.substring(a_start_idx).indexOf("\">");
String externalLink = tmp.substring(a_start_idx, a_end_idx);
externalLinks.add(externalLink);
tmp = tmp.substring(a_end_idx);
}
infos[index].externalLinks = externalLinks;
infos[index].externalLinkCnt = externalLinks.size();
}
static void setBasicScore(Info[] infos, int index, String page, String word) {
String search = "<body>";
int body_start_idx = page.indexOf(search) + search.length();
int body_end_idx = body_start_idx + page.substring(body_start_idx).indexOf("</body>");
String body = page.substring(body_start_idx, body_end_idx).toUpperCase();
body = body.toUpperCase();
word = word.toUpperCase();
int cnt = 0;
int find = body.indexOf(word);
while (find != -1) {
char prev = body.charAt(find - 1);
char next = body.charAt(find + word.length());
if (!Character.isLetter(prev) && !Character.isLetter(next)) {
cnt++;
}
find = body.indexOf(word, find + 1);
}
infos[index].basicScore = cnt;
}
static class Info implements Comparable<Info> {
String url;
ArrayList<String> externalLinks;
int index, basicScore, externalLinkCnt;
double linkScore, matchingScore;
public Info(int index) {
this.index = index;
}
@Override
public int compareTo(Info o) {
return this.matchingScore == o.matchingScore ? this.index - o.index : Double.compare(o.matchingScore, this.matchingScore);
}
}
public static void main(String[] args) {
// solution("blind", new String[]{"<html lang=\"ko\" xml:lang=\"ko\" xmlns=\"http://www.w3.org/1999/xhtml\">\n<head>\n <meta charset=\"utf-8\">\n <meta property=\"og:url\" content=\"https://a.com\"/>\n</head> \n<body>\nBlind Lorem Blind ipsum dolor Blind test sit amet, consectetur adipiscing elit. \n<a href=\"https://b.com\"> Link to b </a>\n</body>\n</html>", "<html lang=\"ko\" xml:lang=\"ko\" xmlns=\"http://www.w3.org/1999/xhtml\">\n<head>\n <meta charset=\"utf-8\">\n <meta property=\"og:url\" content=\"https://b.com\"/>\n</head> \n<body>\nSuspendisse potenti. Vivamus venenatis tellus non turpis bibendum, \n<a href=\"https://a.com\"> Link to a </a>\nblind sed congue urna varius. Suspendisse feugiat nisl ligula, quis malesuada felis hendrerit ut.\n<a href=\"https://c.com\"> Link to c </a>\n</body>\n</html>", "<html lang=\"ko\" xml:lang=\"ko\" xmlns=\"http://www.w3.org/1999/xhtml\">\n<head>\n <meta charset=\"utf-8\">\n <meta property=\"og:url\" content=\"https://c.com\"/>\n</head> \n<body>\nUt condimentum urna at felis sodales rutrum. Sed dapibus cursus diam, non interdum nulla tempor nec. Phasellus rutrum enim at orci consectetu blind\n<a href=\"https://a.com\"> Link to a </a>\n</body>\n</html>"});
solution("Muzi", new String[]{"<html lang=\"ko\" xml:lang=\"ko\" xmlns=\"http://www.w3.org/1999/xhtml\">\n<head>\n <meta charset=\"utf-8\">\n <meta property=\"og:url\" content=\"https://careers.kakao.com/interview/list\"/>\n</head> \n<body>\n<a href=\"https://programmers.co.kr/learn/courses/4673\"></a>#!MuziMuzi!)jayg07con&&\n\n</body>\n</html>", "<html lang=\"ko\" xml:lang=\"ko\" xmlns=\"http://www.w3.org/1999/xhtml\">\n<head>\n <meta charset=\"utf-8\">\n <meta property=\"og:url\" content=\"https://www.kakaocorp.com\"/>\n</head> \n<body>\ncon%\tmuzI92apeach&2<a href=\"https://hashcode.co.kr/tos\"></a>\n\n\t^\n</body>\n</html>"});
}
}
댓글남기기