문제 풀이/프로그래머스
프로그래머스 - 매칭 점수 [C++]
JJJaewon
2024. 3. 2. 22:33
반응형
이 문제는 문자열, 구현 문제이다.
주요 포인트는 대소문자 구별 X, 알파벳을 제외한 모든 문자가 구분자가 되는 단어들 파싱, 내 링크 및 외부 링크 찾기이다.
대소문자 구별을 하지 않는 방법은 전부 대문자나 소문자로 바꿔놓는 것이다. 이는 간단하게 구현할 수 있다.
알파벳을 제외한 모든 문자가 구분자가 되는 단어들을 파싱하기 위해 for문을 돌리면서 'a' <= c && c <= 'z' 를 체크하고, 아닌 경우에는 지금까지 쌓여있던 단어를 리턴 벡터에 저장하는 방식으로 구현했다.
내 링크 및 외부 링크 찾기는 kmp 알고리즘을 사용하여 속도를 높였다. 여기서 주의할 점은 단순히 "http://" 를 찾으면 오답이 나오게 되고, 태그까지 정확히 걸어서 "<a href=\"" 를 검색하게 만들어야 한다. 이 또한 kmp 알고리즘을 외우고만 있으면 쉽게 구현할 수 있다.
위 세 가지를 제외한 부수적인 부분들은 쉽게 구현할 수 있고, 이 요구사항들을 구현만 하면 정답이 나오게 된다.
#include <string>
#include <vector>
#include <iostream>
#include <sstream>
#include <map>
using namespace std;
char toLower(char c)
{
if ('A' <= c && c <= 'Z')
{
return c + ('a' - 'A');
}
else
{
return c;
}
}
vector<string> split(string input)
{
vector<string> result;
string temp = "";
for (char c : input)
{
if ('a' <= c && c <= 'z')
{
temp += c;
}
else
{
if (!temp.empty())
{
result.push_back(temp);
}
temp = "";
}
}
if (!temp.empty())
{
result.push_back(temp);
}
return result;
}
vector<int> getPi(string comp)
{
int m = comp.size();
vector<int> pi(m, 0);
int start = 1;
int matched = 0;
while (start + matched < m)
{
if (comp[start + matched] == comp[matched])
{
matched++;
pi[start + matched - 1] = matched;
}
else
{
if (matched == 0)
{
start++;
}
else
{
start += matched - pi[matched - 1];
matched = pi[matched - 1];
}
}
}
return pi;
}
vector<int> kmp(string all, string comp)
{
int n = all.size();
int m = comp.size();
vector<int> pi = getPi(comp);
vector<int> result;
int start = 0;
int matched = 0;
while (start <= n - m)
{
if (matched < m && all[start + matched] == comp[matched])
{
matched++;
if (matched == m)
{
result.push_back(start);
}
}
else
{
if (matched == 0)
{
start++;
}
else
{
start += matched - pi[matched - 1];
matched = pi[matched - 1];
}
}
}
return result;
}
string getUrl(int index, string& page)
{
string result = "";
for (int i = index; page[i] != '\"'; i++)
{
result += page[i];
}
return result;
}
struct Node
{
string url = "";
int base = 0;
int outer = 0;
double link = 0;
double matching = 0;
};
map<string, int> urlToIndex;
map<string, vector<int>> links;
vector<Node> nodes;
string getMyUrl(string page)
{
vector<int> urlIndex = kmp(page, "<meta property=\"og:url\" content=\"");
string myUrl = getUrl(urlIndex[0] + 33, page);
return myUrl;
}
int calculateBase(string page, string word)
{
vector<string> words = split(page);
int base = 0;
for (string& w : words)
{
if (w == word)
{
base++;
}
}
return base;
}
int calculateOuter(string page, int me)
{
vector<int> urlIndex = kmp(page, "<a href=\"");
int outer = urlIndex.size();
for (int i = 0; i < urlIndex.size(); i++)
{
string url = getUrl(urlIndex[i] + 9, page);
links[url].push_back(me);
}
return outer;
}
void allLower(string& word)
{
for (int i = 0; i < word.size(); i++)
{
word[i] = toLower(word[i]);
}
}
int solution(string word, vector<string> pages)
{
int answer = 0;
allLower(word);
for (int i = 0; i < pages.size(); i++)
{
string& page = pages[i];
allLower(page);
string myUrl = getMyUrl(page);
urlToIndex[myUrl] = i;
int base = calculateBase(page, word);
int outer = calculateOuter(page, i);
nodes.push_back({myUrl, base, outer, 0, 0});
}
double maxValue = -1;
for (int i = 0; i < pages.size(); i++)
{
Node presentNode = nodes[i];
string myUrl = presentNode.url;
double linkScore = 0;
for (int link : links[myUrl])
{
Node nextNode = nodes[link];
linkScore += (double)(nextNode.base) / (nextNode.outer);
}
if (maxValue < linkScore + presentNode.base)
{
maxValue = linkScore + presentNode.base;
answer = i;
}
}
return answer;
}
반응형