int main(){ const int N = 26; std::string a; getline(std::cin, a); std::string b; getline(std::cin, b); std::string c; getline(std::cin, c); std::vector<size_t> acount(N, 0); for(size_t p = 0; p < a.size(); p++){++acount[a[p] - 'a'];} std::vector<size_t> bcount(N, 0); for(size_t p = 0; p < b.size(); p++){++bcount[b[p] - 'a'];} std::vector<size_t> ccount(N, 0); for(size_t p = 0; p < c.size(); p++){++ccount[c[p] - 'a'];} long maxB(a.size()); for(size_t p = 0; p < N; p++){if(bcount[p] > 0 && (acount[p] / bcount[p]) < maxB){maxB = (acount[p] / bcount[p]);}} long maxSum(maxB), optB(maxB), optC(0); for(size_t b = 0; b <= maxB; b++){ size_t candC(a.size()); for(size_t p = 0; p < N; p++){if(ccount[p] > 0 && ((acount[p] - b * bcount[p])/ ccount[p]) < candC){candC = (acount[p] - b * bcount[p])/ccount[p];}} if(b + candC > maxSum){maxSum = b + candC; optB = b; optC = candC;} } for(int p = 0; p < optB; p++){std::cout << b;} for(int p = 0; p < optC; p++){std::cout << c;} for(int p = 0; p < N; p++){ size_t rem = acount[p] - optB * bcount[p] - optC * ccount[p]; while(rem--){std::cout << char('a' + p);} } std::cout << std::endl; return 0; }
/** * calc distance between two items. * Let a be all the users rated item 1 * Let b be all the users rated item 2 * Let intersection (a,b) be the number of users rated both items * Let size(a) be the number of users rated item 1 * Let size(b) be the number of users rated item 2 * * Only for prob similarity: * Let M be the total number of users * Let N be the total number of iterms * Let L be the total number of training ratings * * 0) Using Jackard index: * Dist_12 = intersection(a,b) / (size(a) + size(b) - size(intersection(a,b)) * * 1) Using AA index: * Dist_12 = sum_user k in intersection(a,b) [ 1 / log(degree(k)) ] * * 2) Using RA index: * Dist_12 = sum_user k in intersection(a,b) [ 1 / degree(k) ] * * 3) Using Asym Cosine: * Dist_12 = intersection(a,b) / size(a)^alpha * size(b)^(1-alpha) * * 4) Using prob similarity: * Dist_12 = intersection(a,b) / [ sum(user k in b) p(k,1) ] * where p(k,1) = 1 / [ 1 + (L / (MN-L)) ((N - degree(k))/degree(K)) * ((M - degree(1)) / degree(1)) ] * */ double calc_distance(graphchi_vertex<uint32_t, uint32_t> &v, vid_t pivot, int distance_metric) { //assert(is_pivot(pivot)); //assert(is_item(pivot) && is_item(v.id())); dense_adj &pivot_edges = adjs[pivot - pivot_st]; int num_edges = v.num_edges(); //if there are not enough neighboring user nodes to those two items there is no need //to actually count the intersection if (num_edges < min_allowed_intersection || pivot_edges.count < min_allowed_intersection) return 0; std::vector<vid_t> edges; edges.resize(num_edges); for(int i=0; i < num_edges; i++) { vid_t other_vertex = v.edge(i)->vertexid; edges[i] = other_vertex; } sort(edges.begin(), edges.end()); std::set<vid_t> intersection; std::set_intersection( pivot_edges.adjlist, pivot_edges.adjlist + pivot_edges.count, edges.begin(), edges.end(), std::inserter(intersection, intersection.begin())); double intersection_size = (double)intersection.size(); //not enough user nodes rated both items, so the pairs of items are not compared. if (intersection_size < (double)min_allowed_intersection) return 0; if (distance_metric == JACCARD){ uint set_a_size = v.num_edges(); //number of users connected to current item uint set_b_size = acount(pivot); //number of users connected to current pivot return intersection_size / (double)(set_a_size + set_b_size - intersection_size); //compute the distance } else if (distance_metric == AA){ double dist = 0; for (std::set<vid_t>::iterator i= intersection.begin() ; i != intersection.end(); i++){ vid_t user = *i; assert(latent_factors_inmem.size() == M && is_user(user)); assert(latent_factors_inmem[user].degree > 0); dist += 1.0 / log(latent_factors_inmem[user].degree); } return dist; } else if (distance_metric == RA){ double dist = 0; for (std::set<vid_t>::iterator i= intersection.begin() ; i != intersection.end(); i++){ vid_t user = *i; assert(latent_factors_inmem.size() == M && is_user(user)); assert(latent_factors_inmem[user].degree > 0); dist += 1.0 / latent_factors_inmem[user].degree; } return dist; } /* 3) Using Asym Cosine: * Dist_12 = intersection(a,b) / size(a)^alpha * size(b)^(1-alpha) */ else if (distance_metric == ASYM_COSINE){ uint set_a_size = v.num_edges(); //number of users connected to current item uint set_b_size = acount(pivot); //number of users connected to current pivot return intersection_size / (pow(set_a_size,asym_cosine_alpha) * pow(set_b_size,1-asym_cosine_alpha)); } /* 4) Using prob similarity: * Dist_12 = intersection(a,b) / [ sum(user k in b) p(k,1) ] * where p(k,1) = 1 / [ 1 + (L / (MN-L)) ((N - degree(k))/degree(K)) * ((M - degree(1)) / degree(1)) ] */ else if (distance_metric == PROB){ double sum = 0; for(int i=0; i<pivot_edges.count; i++) { int node_k = pivot_edges.adjlist[i]; int degree_k = latent_factors_inmem[node_k].degree; assert(degree_k > 0); double p_k_1 = 1.0 / ( 1.0 + prob_sim_normalization_constant * ((N - degree_k)/(double)degree_k) * ((M - num_edges) / (double)num_edges)); assert(p_k_1 > 0 && p_k_1 <= 1.0); sum += p_k_1; } return intersection_size / sum; } else { assert(false); } return -1; //just to avoid warning }
/** * calc distance between two items. * Let a be all the users rated item 1 * Let b be all the users rated item 2 * * 1) Using Jackard index: * Dist_ab = intersection(a,b) / (size(a) + size(b) - size(intersection(a,b)) * * 2) Using AA index: * Dist_ab = sum_user k in intersection(a,b) [ 1 / log(degree(k)) ] * * 3) Using RA index: * Dist_ab = sum_user k in intersection(a,b) [ 1 / degree(k) ] * * 4) Using Asym Cosine: * Dist_ab = intersection(a,b) / size(a)^alpha * size(b)^(1-alpha) */ double calc_distance(graphchi_vertex<uint32_t, uint32_t> &v, vid_t pivot, int distance_metric) { //assert(is_pivot(pivot)); //assert(is_item(pivot) && is_item(v.id())); dense_adj &pivot_edges = adjs[pivot - pivot_st]; int num_edges = v.num_edges(); //if there are not enough neighboring user nodes to those two items there is no need //to actually count the intersection if (num_edges < min_allowed_intersection || pivot_edges.count < min_allowed_intersection) return 0; std::vector<vid_t> edges; edges.resize(num_edges); for(int i=0; i < num_edges; i++) { vid_t other_vertex = v.edge(i)->vertexid; edges[i] = other_vertex; } sort(edges.begin(), edges.end()); std::set<vid_t> intersection; std::set_intersection( pivot_edges.adjlist, pivot_edges.adjlist + pivot_edges.count, edges.begin(), edges.end(), std::inserter(intersection, intersection.begin())); double intersection_size = (double)intersection.size(); //not enough user nodes rated both items, so the pairs of items are not compared. if (intersection_size < (double)min_allowed_intersection) return 0; if (distance_metric == JACCARD){ uint set_a_size = v.num_edges(); //number of users connected to current item uint set_b_size = acount(pivot); //number of users connected to current pivot return intersection_size / (double)(set_a_size + set_b_size - intersection_size); //compute the distance } else if (distance_metric == AA){ double dist = 0; for (std::set<vid_t>::iterator i= intersection.begin() ; i != intersection.end(); i++){ vid_t user = *i; assert(latent_factors_inmem.size() == M && is_user(user)); assert(latent_factors_inmem[user].degree > 0); dist += 1.0 / log(latent_factors_inmem[user].degree); } return dist; } else if (distance_metric == RA){ double dist = 0; for (std::set<vid_t>::iterator i= intersection.begin() ; i != intersection.end(); i++){ vid_t user = *i; assert(latent_factors_inmem.size() == M && is_user(user)); assert(latent_factors_inmem[user].degree > 0); dist += 1.0 / latent_factors_inmem[user].degree; } return dist; } else if (distance_metric == ASYM_COSINE){ uint set_a_size = v.num_edges(); //number of users connected to current item uint set_b_size = acount(pivot); //number of users connected to current pivot return intersection_size / (pow(set_a_size,asym_cosine_alpha) * pow(set_b_size,1-asym_cosine_alpha)); } return 0; }