https://school.programmers.co.kr/learn/courses/30/lessons/60060
프로그래머스
SW개발자를 위한 평가, 교육, 채용까지 Total Solution을 제공하는 개발자 성장을 위한 베이스캠프
programmers.co.kr
내가 처음 낸 코드
정규식regex 사용해서 풀어나갔는데
아무래도 속도(효율성) 측면에서 부족한듯 하다.
#include <iostream>
#include<vector>
#include<regex>
#include<string>
using namespace std;
vector<int> solution(vector<string>& words, vector<string>& queries)
{
vector<int> answer;
for (auto& query : queries)
{
string regexPattern = query;
for (char& c : regexPattern)
{
if(c=='?')c = '.';
}
regex r(regexPattern);//정규식 객체 생성
int count = 0;
for (const auto& word : words)
{
if (regex_match(word, r)) //정규식객체가 비교대상인되는 word배열과매칭이되면
{
++count;//카운트를 늘림
}
}
answer.push_back(count);
}
return answer;
}
int main()
{
ios_base::sync_with_stdio(false);
cin.tie(NULL);
cout.tie(NULL);
vector<string> words;
vector<string> key;
cout << "how many words and keywords to type? " << endl;
int n,m ;
cin >> n>>m;
words.resize(n);
key.resize(m);
cout << "type the words" << endl;
for (int i = 0; i < n; i++)
{
cin >> words[i];
}
//for (auto a : words) cout << a << " ";
cout << " type keywords :" << endl;
for (int i = 0; i < m; i++)
{
cin >> key[i];
}
//for (auto a : key) cout << a << " ";
vector<int>ans=solution(words, key);
for (auto a : ans) cout << a << " ";
return 0;
}
#include <iostream>
#include<vector>
#include<regex>
#include<string>
using namespace std;
vector<int> solution(vector<string> words, vector<string> queries)
{
vector<int> answer;
for (auto& query : queries)
{
string regexPattern = query;
for (char& c : regexPattern)
{
if(c=='?')c = '.';
}
regex r(regexPattern);
int count = 0;
for (const auto& word : words)
{
if (regex_match(word, r)) ++count;
}
answer.push_back(count);
}
return answer;
}
대략 시간 복잡도가
O(Q * W * L)
Q 쿼리 수= for (auto& query : queries)
W = 단어 수 for (const auto& word : words) { // O(W) - W는 단어의 수 regex_match(word, r)
L = 문자열의 길이 for (char& c : regexPattern) { ... }
이를 실제 상황에 대입해보면:
이라면, 최악의 경우 약 1,000,000번의 연산이 필요하다는 의미이다.
대규모 데이터의 경우에는 엄청난 연산이 필요하기 때문에 효율성은 ㅜㅜ 아래와 같이 마구 마구 떨어지는 ...
효율성 안녕~~~~
결국 이분탐색으로
#include <iostream>
#include <vector>
#include <algorithm>
#include <string>
using namespace std;
vector<int> solution(const vector<string>& words, const vector<string>& queries)
{
//?가 앞에 있는 쿼리를 효과적으로 처리하기 위해 reversedWordGroups활용(eg. eppl? vs epplA)
vector<vector<string>> wordGroups(10001), reversedWordGroups(10001);
for (const auto& word : words)
{
//쿼리의 길이와 단어의 길이가 다르면 절대 매칭되지 않기 때문에 사이즈별로 나눠 탐색대상을 줄임
wordGroups[word.size()].push_back(word);
string reversedWord = word;
reverse(reversedWord.begin(), reversedWord.end());
reversedWordGroups[word.size()].push_back(reversedWord);//사이즈별로 뒤집어서 저장
}
//binary search는 정렬이된 배열에서만 정상작동!!!
for (auto& group : wordGroups) sort(group.begin(), group.end());
for (auto& group : reversedWordGroups) sort(group.begin(), group.end());
vector<int> answer;
for (const auto& query : queries)
{
int len = query.size();
if (wordGroups[len].empty())
{
// 해당 길이의 단어가 없는 경우
answer.push_back(0);
continue;
}
// 물음표 위치 확인
if (query[0] != '?')
{
// 물음표가 뒤에 있는 경우
string start = query;//검색 시작점
string end = query;
// 쿼리의 물음표(?)를 a(최소값)와 z(최대값)으로 치환하여 검색 범위를 확정
replace(start.begin(), start.end(), '?', 'a'); //예: "app??" → start = "appaa"
replace(end.begin(), end.end(), '?', 'z'); // 최대값 예:end = "appzz"
//end(예: "appzz")보다 큰 첫 번째 위치 - start(예: "appaa")보다 크거나 같은 첫 번째 위치
int count = upper_bound(wordGroups[len].begin(), wordGroups[len].end(), end) -
lower_bound(wordGroups[len].begin(), wordGroups[len].end(), start);
answer.push_back(count);
}
else
{
// 물음표가 앞에 있는 경우
string reversedQuery = query;
reverse(reversedQuery.begin(), reversedQuery.end());//쿼리도 귀집기 ??ple->elp??
string start = reversedQuery;
string end = reversedQuery;
replace(start.begin(), start.end(), '?', 'a'); //??ple->aaple
replace(end.begin(), end.end(), '?', 'z'); //??ple->zzple
int count = upper_bound(reversedWordGroups[len].begin(), reversedWordGroups[len].end(), end) -
lower_bound(reversedWordGroups[len].begin(), reversedWordGroups[len].end(), start);
answer.push_back(count);
}
}
return answer;
}
int main() {
ios_base::sync_with_stdio(false);
cin.tie(NULL);
int n, m;
cin >> n >> m;
vector<string> words(n);
vector<string> queries(m);
for (int i = 0; i < n; i++) cin >> words[i];
for (int i = 0; i < m; i++) cin >> queries[i];
vector<int> result = solution(words, queries);
for (int i : result) cout << i << "\n";
return 0;
}
물음표가 뒤에 있을 때 예제
물음표가 앞에 있을 때 예제
현재 이분탐색 방식:
이전 정규식 방식
실제 예시로 비교하자면 (W=1000, Q=100, L=10 일 때):
이분탐색법이 대략 100배 효율적이다~!
따라서, 전체 시간 복잡도는 O(WlogW+QlogW)O(W \log W + Q \log W)입니다.
vector<string> words = {"frodo", "front", "frost", "frozen", "frame", "kakao"};
vector<string> queries = {"fro??", "????o", "fr???", "fro???", "pro?"};
vector<int> result = solution(words, queries);
// result: {3, 2, 4, 1, 0}
해석:
Programmers 64064 불량 사용자 (0) | 2025.02.11 |
---|---|
Programmers 양과 늑대 (0) | 2025.01.22 |
백준 17825 주사위 윷놀이 (0) | 2025.01.21 |
백준 17270// 연예인은 힘들어//다익스트라 알고리즘 (Dijkstra's Algorithm)// (0) | 2025.01.20 |
항해 99 //백준 11657 //타임머신//벨만 포드(Bellamn- Ford) 알고리즘 (0) | 2025.01.13 |