본문 바로가기

알고리즘 공부 및 문제 풀이/프로그래머스(PRO)

[pro] 프로그래머스 level3 42893 매칭 점수 (Java) - 문자열, 정규식

[문제]

https://school.programmers.co.kr/learn/courses/30/lessons/42893

 

프로그래머스

코드 중심의 개발자 채용. 스택 기반의 포지션 매칭. 프로그래머스의 개발자 맞춤형 프로필을 등록하고, 나와 기술 궁합이 잘 맞는 기업들을 매칭 받으세요.

programmers.co.kr

 

[풀이]

정규식을 이용해서 풀 수 있다.

 

1) word가 나오는 횟수를 계산해서 기본 점수를 구한다. 이때 주의할 점은 찾은 word 앞, 뒤로 다른 문자가 있으면 안된다. 

2) 페이지별 외부 링크 개수를 계산한다.

3) 정규식을 이용하여 링크 점수를 계산한다.

 

Page 별로 url을 파싱해서 저장해놓는데, () 로 묶어서 group화 할 수 있다. 전체 pattern에 일치하는 문자열을 group() 또는 group(0)으로 가져올 수 있고, ()로 묶은 그룹이 하나밖에 없으므로 group(1)로 해당 칸의 문자열을 가져와 저장할 수 있다. (.+?) 에서 .은 어떤 문자에 대해서 1개 이상 등장하는 문자열을 의미한다. 

 

[코드]

 

import java.util.*;
import java.util.regex.*;

class Solution {
    Map<String, Page> hm = new HashMap<>();

    public int solution(String word, String[] pages) {
        int idx = 0;
        for (String html : pages) {
            Page page = new Page(idx++, html.toLowerCase());
            page.calDefaultScore(word.toLowerCase());
            page.calLinkCount();
            hm.put(page.url, page);
        }

        for (Page page : hm.values()) {
            page.calLinkScore();
        }

        ArrayList<Page> list = new ArrayList(hm.values());
        Collections.sort(list);

        return list.get(0).idx;
    }

    class Page implements Comparable<Page> {
        int idx;
        int defaultScore = 0;
        int linkCount = 0;
        double linkScore = 0;
        String html, url;

        Page(int idx, String html) {
            this.idx = idx;
            this.html = html;
            findUrl();
        }

        private void findUrl() {
            Pattern pattern = Pattern.compile("<meta property=\"og:url\" content=\"https://(.+?)\"/>");
            Matcher matcher = pattern.matcher(html);
            while (matcher.find()) {
                url = matcher.group(1);
            }
        }

        public void calDefaultScore(String word) {
            int idx = html.indexOf(word);
            while (idx != -1) {
                char pre = html.charAt(idx - 1);
                char post = html.charAt(idx + word.length());

                if ((pre<'a' || pre>'z') && (post<'a'||post>'z')) {
                    defaultScore++;
                }
                idx = html.indexOf(word, idx + 1);
            }
        }

        public void calLinkCount() {
            int idx = html.indexOf("<a href=");
            while (idx != -1) {
                linkCount++;
                idx = html.indexOf("<a href=", idx + 1);
            }
        }

        public void calLinkScore() {
            Pattern pattern = Pattern.compile("<a href=\"https://(.+?)\">");
            Matcher matcher = pattern.matcher(html);
            while (matcher.find()) {
                String extraUrl = matcher.group(1);
                if (hm.containsKey(extraUrl)) {
                    hm.get(extraUrl).linkScore += (double) defaultScore / linkCount;
                }
            }
        }

        @Override
        public int compareTo(Page other) {
            double a = (double) this.defaultScore + this.linkScore;
            double b = (double) other.defaultScore + other.linkScore;

            return Double.compare(b, a);
        }
    }
}