[BOJ] 16139번 | 인간-컴퓨터 μƒν˜Έμž‘μš© (C++)

2023. 8. 27. 17:46ㆍCoding Test/BOJ

πŸ”—λ¬Έμ œ λ³΄λŸ¬κ°€κΈ°
 

16139번: 인간-컴퓨터 μƒν˜Έμž‘μš©

첫 쀄에 λ¬Έμžμ—΄ $S$κ°€ 주어진닀. λ¬Έμžμ—΄μ˜ κΈΈμ΄λŠ” $200,000$자 μ΄ν•˜μ΄λ©° μ•ŒνŒŒλ²³ μ†Œλ¬Έμžλ‘œλ§Œ κ΅¬μ„±λ˜μ—ˆλ‹€. 두 번째 μ€„μ—λŠ” 질문의 수 $q$κ°€ 주어지며, 문제의 μˆ˜λŠ” $1\leq q\leq 200,000$을 λ§Œμ‘±ν•œλ‹€. μ„Έ 번째

www.acmicpc.net

 

πŸ§‘‍πŸ’»ν’€μ΄ κ³Όμ •


λ‚˜μ˜ λ©μ²­ν•œ μ‹€μˆ˜

이전 λ¬Έμ œμ—μ„œ λˆ„μ  합을 잘 ꡬ해놓고, μ—¬κΈ°μ—μ„œλŠ” μ™œ μ μš©μ„ λͺ»ν–ˆλ‚˜ μ‹ΆμŠ΅λ‹ˆλ‹€..

μ²˜μŒμ—λŠ” DP[26][S.length()] 배열을 μ„ μ–Έν•˜μ—¬, 각 μ•ŒνŒŒλ²³λ§ˆλ‹€ λ“±μž₯ν•œ 횟수λ₯Ό λˆ„μ ν•˜μ—¬ μ €μž₯ν•˜λŠ” λ°©μ‹μœΌλ‘œ μ ‘κ·Όν•˜μ˜€μŠ΅λ‹ˆλ‹€.

const int ALPHABET_COUNT = 26;
const int LOWER_A_ASCII = 97;
string S;

vector<vector<int>> DP(ALPHABET_COUNT, vector<int>(S.length()));
for (int i = 0; i < S.length(); i++)
{
    // i-1번 μ—΄μ˜ λˆ„μ  κ°œμˆ˜λ“€ κ·ΈλŒ€λ‘œ κ°€μ Έμ˜€κΈ°
    for (int j = 0; (i != 0) and (j < ALPHABET_COUNT); j++)
        if (DP[j][i-1] != 0)
        	DP[j][i] = DP[j][i-1];
    
    // S[i]에 ν•΄λ‹Ήν•˜λŠ” μ•ŒνŒŒλ²³ 개수 μΆ”κ°€
    int index = S[i] - LOWER_A_ASCII;
    DP[index][i]++;
}

 

μ΄λ ‡κ²Œ 잘 ꡬ해놓고, μ™œ μ§ˆλ¬Έμ—μ„œ DP[alphabet][r] - DP[alphabet][l - 1]을 생각 λͺ» ν–ˆλ‚˜ μ‹Άλ„€μš”...

μ•„λ¬΄νŠΌ, μœ„ 식을 생각 λͺ»ν•˜λŠ” λ°”λžŒμ— 이진 탐색(Binary Search)둜 풀이 λ°©ν–₯을 λ°”κΎΈμ—ˆμŠ΅λ‹ˆλ‹€..

 

이진 탐색 방식 μ ‘κ·Ό

  1. 주어진 S λ¬Έμžμ—΄μ—μ„œ, 각각의 μ•ŒνŒŒλ²³λ“€μ΄ λ“±μž₯ν•˜λŠ” 인덱슀 μœ„μΉ˜λ“€μ„ λ°°μ—΄λ‘œ λ‹΄μ•˜μŠ΅λ‹ˆλ‹€.
    • for 문으둜 순차 νƒμƒ‰ν•œ 거라, μžλ™μœΌλ‘œ μ˜€λ¦„μ°¨μˆœ 정렬이 λ˜μ–΄ μžˆμŠ΅λ‹ˆλ‹€.
  2. λ¬Έμ œμ—μ„œ 주어진 l, r에 λŒ€ν•˜μ—¬, lμ—λŠ” lower_bound(), rμ—λŠ” upper_bound()λ₯Ό μ μš©ν•©λ‹ˆλ‹€.
    • lower_bound()와 upper_bound() κ²°κ³Ό 각각에 vector.begin()을 λΉΌλ©΄ 인덱슀 λ²ˆν˜Έκ°€ λ‚˜μ˜΅λ‹ˆλ‹€.
  3. 2λ²ˆμ—μ„œ κ΅¬ν•œ 인덱슀 번호 차이가 μ •λ‹΅μž…λ‹ˆλ‹€.

 

βœοΈμ†ŒμŠ€ μ½”λ“œ 및 κ²°κ³Ό

#include <iostream>
#include <vector>
#include <string>
#include <algorithm>
using namespace std;
const int ALPHABET_COUNT = 26;
const int LOWER_A_ASCII = 97;

int main()
{
	ios::sync_with_stdio(false);
	cout.tie(NULL); cin.tie(NULL);

	int quesitionCount;
	string sequence;
	cin >> sequence >> quesitionCount;

	// 1. 각 μ•ŒνŒŒλ²³λ§ˆλ‹€, λ‚˜μ˜€λŠ” μœ„μΉ˜λ“€μ„ μ €μž₯
	vector<vector<int>> alphabetPositions(ALPHABET_COUNT);
	for (int i = 0; i < sequence.length(); i++)
	{
		int index = sequence[i] - LOWER_A_ASCII;
		alphabetPositions[index].emplace_back(i);
	}

	// 2. 이진 탐색을 μ΄μš©ν•˜μ—¬, 인덱슀 차이λ₯Ό 계산 ν›„ 좜λ ₯
	for (int i = 0; i < quesitionCount; i++)
	{
		char find;
		int l, r;
		cin >> find >> l >> r;

		int index = find - LOWER_A_ASCII;
		int start = lower_bound(alphabetPositions[index].begin(), alphabetPositions[index].end(), l) - alphabetPositions[index].begin();
		int last = upper_bound(alphabetPositions[index].begin(), alphabetPositions[index].end(), r) - alphabetPositions[index].begin();

		cout << last - start << "\n";
	}

	return 0;
}

 

728x90
λ°˜μ‘ν˜•