https://programmers.co.kr/learn/courses/30/lessons/17677
두 개의 문자열에 대해 자카드 유사도를 구하는 문제이다.
자카드 유사도라는 것 자체가 생소했는데,
문제에 자세히 설명이 되어있어서 이해하기에는 어렵지 않았다.
지난 번 프로그래머스 문제를 풀 때
STL을 잘 활용하지 못해서 빙 돌아갔던 게 생각이 나서
이번에는 구현하기 전에 무조건 구글링을 했다!
새삼 C++엔 지원되는 함수가 정말 많은 거 같다
// 교집합
vector<string> intersection(multiSet_A.size() + multiSet_B.size());
auto iter_a = set_intersection(multiSet_A.begin(), multiSet_A.end(), multiSet_B.begin(), multiSet_B.end(), intersection.begin());
intersection.erase(iter_a, intersection.end()); // 남는 공간 비워주기
// 합집합
vector<string> multi_union(multiSet_A.size() + multiSet_B.size());
auto iter_b = set_union(multiSet_A.begin(), multiSet_A.end(), multiSet_B.begin(), multiSet_B.end(), multi_union.begin());
multi_union.erase(iter_b, multi_union.end());
intersection.erase(unique(intersection.begin(), intersection.end()), intersection.end()); // 교집합 중복 제거
for(iter = intersection.begin(); iter != intersection.end(); iter++)
{
counts_min[idx] = min(count(multiSet_A.begin(), multiSet_A.end(), *iter), count(multiSet_B.begin(), multiSet_B.end(), *iter));
counts_max[idx++] = max(count(multiSet_A.begin(), multiSet_A.end(), *iter), count(multiSet_B.begin(), multiSet_B.end(), *iter));
}
구현해야 할 핵심 기능 정리
#include <iostream>
#include <algorithm>
#include <string>
#include <vector>
using namespace std;
#define MUL 65536
int solution(string str1, string str2) {
vector<string> multiSet_A;
vector<string> multiSet_B;
vector<string> ::iterator iter;
for(int i=0; i<str1.length()-1; i++)
{
string tmp;
if(isalpha(str1[i]) && isalpha(str1[i+1]))
{
tmp += tolower(str1[i]);
tmp += tolower(str1[i+1]);
multiSet_A.push_back(tmp);
}
}
for(int i=0; i<str2.length()-1; i++)
{
string tmp;
if(isalpha(str2[i]) && isalpha(str2[i+1]))
{
tmp += tolower(str2[i]);
tmp += tolower(str2[i+1]);
multiSet_B.push_back(tmp);
}
}
if(multiSet_A.size() == 0 && multiSet_B.size() == 0) // 다중집합 A, B가 모두 공집합인 경우
{
return MUL;
}
sort(multiSet_A.begin(), multiSet_A.end());
sort(multiSet_B.begin(), multiSet_B.end());
vector<string> intersection(multiSet_A.size() + multiSet_B.size());
auto iter_a = set_intersection(multiSet_A.begin(), multiSet_A.end(), multiSet_B.begin(), multiSet_B.end(), intersection.begin());
intersection.erase(iter_a, intersection.end()); // 남는 공간 비워주기
// 다중집합의 합집합
vector<string> multi_union(multiSet_A.size() + multiSet_B.size());
auto iter_b = set_union(multiSet_A.begin(), multiSet_A.end(), multiSet_B.begin(), multiSet_B.end(), multi_union.begin());
multi_union.erase(iter_b, multi_union.end());
int Jaccard = 0;
Jaccard = ((float)intersection.size() / (float)multi_union.size()) * 65536;
cout<<Jaccard<<endl;
return Jaccard;
}
CODE (바보버전..)
#include <iostream>
#include <algorithm>
#include <string>
#include <vector>
using namespace std;
#define MUL 65536
int solution(string str1, string str2) {
vector<string> multiSet_A;
vector<string> multiSet_B;
vector<string> ::iterator iter;
for(int i=0; i<str1.length()-1; i++)
{
string tmp;
if(isalpha(str1[i]) && isalpha(str1[i+1]))
{
tmp += tolower(str1[i]);
tmp += tolower(str1[i+1]);
multiSet_A.push_back(tmp);
}
}
for(int i=0; i<str2.length()-1; i++)
{
string tmp;
if(isalpha(str2[i]) && isalpha(str2[i+1]))
{
tmp += tolower(str2[i]);
tmp += tolower(str2[i+1]);
multiSet_B.push_back(tmp);
}
}
if(multiSet_A.size() == 0 && multiSet_B.size() == 0) // 다중집합 A, B가 모두 공집합인 경우
{
return MUL;
}
sort(multiSet_A.begin(), multiSet_A.end());
sort(multiSet_B.begin(), multiSet_B.end());
// 일반 교집합
vector<string> intersection(multiSet_A.size() + multiSet_B.size());
auto iter_a = set_intersection(multiSet_A.begin(), multiSet_A.end(), multiSet_B.begin(), multiSet_B.end(), intersection.begin());
intersection.erase(iter_a, intersection.end()); // 남는 공간 비워주기
//-----------------------이 부분이 전혀 필요가 없음-------------------------
intersection.erase(unique(intersection.begin(), intersection.end()), intersection.end()); // 교집합 중복 제거
// 교집합 내 원소의 최소/최대 개수
int counts_min[intersection.size()];
int counts_max[intersection.size()];
int idx = 0;
for(iter = intersection.begin(); iter != intersection.end(); iter++)
{
counts_min[idx] = min(count(multiSet_A.begin(), multiSet_A.end(), *iter), count(multiSet_B.begin(), multiSet_B.end(), *iter));
counts_max[idx++] = max(count(multiSet_A.begin(), multiSet_A.end(), *iter), count(multiSet_B.begin(), multiSet_B.end(), *iter));
}
// 다중집합의 교집합
vector<string> multi_intersection;
idx = 0;
for(iter = intersection.begin(); iter!= intersection.end(); iter++)
{
for(int i=0; i<counts_min[idx]; i++)
{
multi_intersection.push_back(*iter);
}
idx++;
}
//-----------------------------------------------------------------------
// 다중집합의 합집합
vector<string> multi_union(multiSet_A.size() + multiSet_B.size());
auto iter_b = set_union(multiSet_A.begin(), multiSet_A.end(), multiSet_B.begin(), multiSet_B.end(), multi_union.begin());
multi_union.erase(iter_b, multi_union.end());
// 자카드 유사도 계산
int Jaccard = 0;
Jaccard = ((float)multi_intersection.size() / (float)multi_union.size()) * 65536;
return Jaccard;
}