https://programmers.co.kr/learn/courses/30/lessons/17677

 

코딩테스트 연습 - [1차] 뉴스 클러스터링

뉴스 클러스터링 여러 언론사에서 쏟아지는 뉴스, 특히 속보성 뉴스를 보면 비슷비슷한 제목의 기사가 많아 정작 필요한 기사를 찾기가 어렵다. Daum 뉴스의 개발 업무를 맡게 된 신입사원 튜브

programmers.co.kr

먼저 map을 이용해서 {특정문자열, 존재하는 개수}의 형태로 주어지는 string에 대하여 map을 만들어준다. (코드에서 makeMap 함수)

 

만들기 전에, 대소문자는 구분하지 않는다는 조건을 처리하기 위해서 주어지는 문자열을 모두 소문자로 변환한다.

 

대문자로 변환해도 무관하다.

 

그리고 공집합인 경우를 처리한다.

 

교집합의 경우, 비어있는 map을 생성하고, 한 문자열에 대한 map의 원소가 다른 문자열의 map 원소에 존재하는지 확인하면서, 존재하는 경우에만 새로운 map에 추가해주면 된다.

 

이 때, 교집합에서는 특정원소의 존재하는 개수는 min 값을 사용하기 때문에, 더 작은 값을 넣어주면 된다.

 

합집합의 경우, 특정 문자열의 map에 다른 문자열 map의 원소를 합쳐주면 된다. 따라서 존재하지 않는 경우에는 새롭게 추가해주고, 존재하는 경우에는 더 큰 개수의 값을 넣어주면 된다.

 

#include<bits/stdc++.h>
using namespace std;
map<string, int> mp1, mp2;

map<string, int> makeMap(string str){
    map<string, int> mp;
    
    for(int i = 0 ; i < str.length()-1 ; i++){
        
        // 알파벳 아닌 문자 거르기
        if(!('a' <= str[i] && str[i] <= 'z'))
            continue;
        else if(!('a' <= str[i+1] && str[i+1] <= 'z'))
            continue;
        
        string key = str.substr(i, 2);
        if(mp.find(key) == mp.end()){
            mp.insert({key, 1}); //map에 없으면 추가
        }
        else{
            mp[key]++; //있으면 개수 증가
        }
    }
    return mp;
}
int solution(string str1, string str2) {
    int answer = 0;
    
    // 전부 소문자로 바꾸기
    transform(str1.begin(), str1.end(), str1.begin(), ::tolower);
    transform(str2.begin(), str2.end(), str2.begin(), ::tolower);
    
    mp1 = makeMap(str1); //집합 생성
    mp2 = makeMap(str2);
    
    if(mp1.size() == 0 && mp2.size() == 0){ // 공집합이라 연산 불가능
        return 65536;
    }

    
    int down = 0, up = 0; //분자, 분모
    map<string, int> res; //합집합
    for(auto itr1 = mp1.begin() ; itr1 != mp1.end() ;itr1++){
        string cur = itr1->first;
        
        if(mp2.find(cur) != mp2.end()){
            //있으면(없으면 처리할 게 없음)
            res.insert({cur, min(itr1->second, mp2[cur])});
        }
        up += res[cur];
    }
    
    //교집합
    for(auto itr2 = mp2.begin() ; itr2 != mp2.end() ; itr2++){
        string cur = itr2->first;
        if(mp1.find(cur) != mp1.end()){
            // 있으면
            mp1[cur] = max(itr2->second, mp1[cur]);
        }
        else{
            //없으면
            mp1.insert({cur, itr2->second});
        }
    }
    
    //분모계산(교집합)
    for(auto itr1 = mp1.begin() ; itr1 != mp1.end() ;itr1++){
        down += itr1->second;
    }
       
    answer = up*65536/down;
    return answer;
}

https://www.acmicpc.net/problem/9935



주어진 문자열을 처음부터 끝까지 한 번만 검사한다.


검사하면서, 폭발 단어의 마지막 철자와 같은 철자가 나오면, 현재까지 만들어둔 정답이 폭발 단어를 포함하는지 확인한다.


만약 포함한다면, 필요한 횟수만큼 pop_back 해주고, 그렇지 않으면 이어서 해당 철자를 이어서 붙여준다.



1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
#include<iostream>
#include<string>
 
using namespace std;
 
string ans = "";
int main(void) {
    string str, bomb;
    cin >> str >> bomb;
    
    int k = 0//str의 길이만큼 확인 (확인할 인덱스)
    while (k < (int)str.length()) {
 
        //단어폭탄의 마지막 문자와 같으면서, 단어 폭탄의 길이 이상의 단어가 ans 문자열에 들어 있을 때만 검사
        if (str[k] == bomb[bomb.length() - 1&& ans.length() >= bomb.length()-1) {
            bool isBomb = true;
            int idx = 0;
            for (int j = 1; j <= bomb.length()-1; j++) { //마지막 문자는 어짜피 같으니까, 제외하고 검사
                if (ans[ans.length() - bomb.length() + j] != bomb[idx]) {
                    isBomb = false;
                    break;
                }
                else
                    idx++;
            }
            if (isBomb) { //단어 폭탄인 경우 
                for (int i = 0; i < bomb.length() - 1; i++)
                    ans.pop_back();
            }
            else //폭탄검사를 했는데 아닌 경우
                ans += str[k];
        }
        else { //단어 폭탄의 마지막 철자와 글자가 달랐던 (평범한) 경우
            ans += str[k];
        }
        k++//확인하는 문자열 위치 증가
    }
    if ((int)ans.length() != 0)
        cout << ans;
    else
        cout << "FRULA"
    return 0;
}
cs




https://www.acmicpc.net/problem/1764


set에 들어보지 못한 사람 저장하고, 처음 본사람 이름을 받으면서 set에 있으면 결과 벡터에 담고, 마지막에 정렬 이후 출력


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
#pragma warning(disable :4996)
#include<iostream>
#include<set>
#include<string>
#include<vector>
#include<algorithm>
using namespace std;
 
set<string> lis;
vector<string> see;
int main(void) {
    ios::sync_with_stdio(false);
    cin.tie(0);
    
    int n, m;
    cin >> n >> m;
    
    for (int i = 0; i < n; i++) {
        string temp;
        cin >> temp;
        lis.insert(temp);
    }
    
    for (int i = 0; i < m; i++) {
        string temp;
        cin >> temp;
        if (lis.find(temp) != lis.end()) //lis set에 존재하면 결과에 push
            see.push_back(temp);
    }
    
    sort(see.begin(), see.end());
    cout << see.size() << '\n';
    for (int i = 0; i < see.size(); i++)
        cout << see[i] << '\n';
    
    return 0;
}
 
 
cs


https://www.acmicpc.net/problem/1032




문자열을 입력 받을 때마다, 달라지는 부분을 '?'로 변경해주면 된다.



1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
#pragma warning(disable :4996)
#include<iostream>
#include<string>
#include<vector>
using namespace std;
vector<string> v;
 
int main(void) {
    ios::sync_with_stdio(false);
    cin.tie(0);
    //첫 입력으로 초기화 하고, 다른 부분 ?로 다 바꾸기(이미 ?가 아닌 경우에)
    int n;
    cin >> n;
    string str;
    cin >> str;
    for (int i = 0; i < n - 1; i++) {
        string val;
        cin >> val;
        
        for (int i = 0; i < str.length(); i++) {
            if (str[i] != '?' && str[i] != val[i])
                str[i] = '?';
        }
 
    }
    cout << str;
    return 0;
}
 
 
cs


https://www.acmicpc.net/problem/2941


주어진 경우의 수를 모두 처리해주면 된다.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
#pragma warning(disable :4996)
#include<iostream>
#include<string>
using namespace std;
 
int main(void) {
    ios::sync_with_stdio(false);
    cin.tie(0);
    string str;
    cin >> str;
    
    int i = 0, cnt = 0;
    while (i < str.length()) {
 
        if (str[i] == 'c') {
            if (i < str.length() - 1 &&  str[i + 1== '=' || str[i + 1== '-'
                i += 2;
            else 
                i++;
            
            cnt++;
        }
        else if (str[i] == 'd') {
            if (i < str.length() - 2 && str[i + 1== 'z' && str[i + 2== '=') {
                i += 3;
            }
            else if (i < str.length() - 1 && str[i + 1== '-') {
                i += 2;
            }
            else {
                i++;
            }
            cnt++;
        }
        else if (str[i] == 'l') {
            
            if (i < str.length() - 1 && str[i + 1== 'j')
                i += 2;
            else
                i++;
            cnt++;
        }
        else if (str[i] == 'n' ) {
            if (i < str.length() - 1 && str[i + 1== 'j')
                i += 2;
            else
                i++;
            cnt++;
        }
        else if (str[i] == 's' ) {
            if (i < str.length() - 1 && str[i + 1== '=')
                i += 2;
            else
                i++;
            cnt++;
        }
        else if (str[i] == 'z' && str[i + 1== '=') {
            if (str[i + 1== '=')
                i += 2;
            else
                i++;
            cnt++;
        }
        else {
            cnt++;
            i++;
        }
    }
    cout << cnt;
    return 0;
}
 
 
cs


https://www.acmicpc.net/problem/1316


알파벳 26개 배열을 만들어서 해결



1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
#pragma warning(disable :4996)
#include<iostream>
#include<string>
using namespace std;
 
int alp[26];
int main(void) {
    ios::sync_with_stdio(false);
    cin.tie(0);
 
    string str;
    
    int n, ret = 0;
    cin >> n;
    while (n--) {
        cin >> str;
        bool isBreak = false;
        for (int i = 0; i < str.length(); i++) {
            if (alp[str[i] - 'a'> 0 && str[i] != str[i-1]) {
                isBreak = true;
                break//이전 문자와 다른데, 이전에 나온적이 있는 단어인 경우
            }
            alp[str[i] - 'a']++;
        }
        if (!isBreak) 
            ret++;
 
        for (int i = 0; i < 26; i++)
            alp[i] = 0;
    }
    cout << ret;
    return 0;
}
 
cs


https://www.acmicpc.net/problem/1157




1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
#pragma warning(disable :4996)
#include<iostream>
#include<string>
using namespace std;
 
int alp[26];
int main(void) {
    ios::sync_with_stdio(false);
    cin.tie(0);
    
    string str;
    cin >> str;
    
    for (int i = 0; i < str.length(); i++) {
        if (str[i] >= 'a' && str[i] <= 'z')
            alp[str[i] - 'a']++;
        else
            alp[str[i] - 'A']++;
    }
    
    int Max = 0, idx =0;
    for (int i = 0; i < 26; i++) {
        if (Max < alp[i]) {
            idx = i;
            Max = alp[i];
        }
    }
    
    for (int i = 0; i < 26; i++) {
        if (alp[i] == Max && i != idx) {
            cout << "?";
            return 0;
        }
    }
 
    char ans = idx + 'A';
    cout << ans;
    return 0;
}
 
cs


https://www.acmicpc.net/problem/10809


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
#pragma warning(disable :4996)
#include<iostream>
#include<string>
using namespace std;
int alp[26];
int main(void) {
    //ios::sync_with_stdio(false);
    cin.tie(0);
    
    string str;
    cin >> str;
 
    for (int i = 0; i < 26; i++)
        alp[i] = -1;
    for (int i = 0; i < str.length(); i++) {
        if (alp[str[i] - 'a'== -1)
            alp[str[i] - 'a'= i;
    }
    for (int i = 0; i < 26; i++)
        if (alp[i] >= 0cout << alp[i] << ' ';
        else
            cout << -1 << ' ';
 
    return 0;
}
 
cs


https://www.acmicpc.net/problem/1152


공백을 포함한 문자열을 받을 때는



getline(cin, string변수);


이와 같이 사용한다. 다만 이를 다른 입력과 함께 사용할 경우 버퍼에 개행이 포함되어 개행이 누락되는 경우가 있기 때문에 조심해야 한다. 이 문제의 경우에는 입력을 한 번만 받기 때문에 상관이 없었지만, 조심해야 한다.




1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
#include<iostream>
#include<string>
using namespace std;
 
int main(void) {
    char chr[1000001];
    //cin >> str;
    string str;
    getline(cin, str);
 
 
    int cnt = 0;
    bool findOne = false, findSpace = false;
    //첫번째 단어를 찾았는지, 현재 공백이 등장한 상태인지
 
    for (int i = 0; i < str.length(); i++) {
        if (!findOne && str[i] != ' ') {
            findOne = true;
            cnt++;
            continue;
        }
        else if(findOne) {
            if (str[i] == ' ') findSpace = true;
            else {
                if (findSpace) {
                    cnt++;
                    findSpace = false;
                }
            }
        }
    
    }
    cout << cnt << '\n';
    return 0;
}
cs


https://programmers.co.kr/learn/courses/30/lessons/12916



1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#include <string>
#include <iostream>
#include<algorithm>
using namespace std;
 
int cnt[2];
bool solution(string s)
{
    transform(s.begin(), s.end(), s.begin(), ::tolower);
    for (int i = 0; i < s.length(); i++) {
        if (s[i] == 'p') cnt[0]++;
        else if (s[i] == 'y') cnt[1]++;
    }
    if (cnt[0== cnt[1]) return 1;
    else return 0;
 
}
cs


+ Recent posts