티스토리 뷰
https://www.acmicpc.net/problem/1593
1593번: 문자 해독
첫째 줄에 고고학자들이 찾고자 하는 단어 W의 길이 g와 발굴된 벽화에서 추출한 문자열 S의 길이 |S|가 빈 칸을 사이에 두고 주어진다. (1≤g≤3000, g≤|S|≤3,000,000) 둘째 줄에 W, 셋째 줄에 S의 실
www.acmicpc.net
난이도
DFS(X), 투포인터(O) / 난이도 ⭐️⭐️⭐️
문제 풀이
투포인터(sliding window)를 써야하는 문제이다.
처음 풀이법은 다음과 같다. 시간 초과난 로직이다.
1) 주어진 단어인 cAda를 활용해 만들 수 있는 모든 단어 조합을 구한다.
2) 단어 조합을 돌면서 문자열 AbrAcadAbRa 에 단어가 포함되어 있는지 검사한다.
주어지는 단어는 최대 3000개 알파벳으로 구성될 수 있다.
3000개 알파벳으로 만들 수 있는 길이 3000짜리 모든 단어 조합은??
+ map 대신에 unordered_map을 사용하니 더 빨라졌다.
map - 300ms
unrodered_map - 192ms

맞는 풀이
// https://www.acmicpc.net/problem/1593
#include <iostream>
#include <vector>
#include <string>
#include <unordered_map>
using namespace std;
int w_cnt, s_cnt;
string w, s;
int result;
bool is_alph_consist_same(unordered_map<char, int> &m1, unordered_map<char, int> &m2)
{
unordered_map<char, int>::iterator iter;
int key;
int value;
for (iter = m1.begin(); iter != m1.end(); iter++)
{
key = iter->first;
value = iter->second;
if (m2.find(key) != m2.end())
{ // exist
if (m2[key] != value)
{
return false;
}
}
else
{
return false;
}
}
return true;
}
int main()
{
ios_base::sync_with_stdio(false);
cin.tie(NULL);
cout.tie(NULL);
// 1. 입력
cin >> w_cnt >> s_cnt;
cin >> w;
cin >> s;
// 2. 입력받은 w, s 문자열에 대해 w_cnt만큼 검사하면서 map에 저장
// w_cnt = 4라면 0~3을 검사하면서 map[알파벳] = 개수 형태로 저장
unordered_map<char, int> m;
unordered_map<char, int> m2;
for (int i = 0; i < w_cnt; i++)
{
if (m.find(w[i]) != m.end()) // exist
{
m[w[i]]++;
}
else
{ // non exist
m[w[i]] = 1;
}
}
for (int i = 0; i < w_cnt; i++)
{
if (m2.find(s[i]) != m2.end()) // exist
{
m2[s[i]]++;
}
else
{ // non exist
m2[s[i]] = 1;
}
}
// w, s에 대해 특정 구간안에 포함된 알파벳 구성이 같은지 검사
if (is_alph_consist_same(m, m2))
result += 1;
// 3. 투포인터
// window를 한칸씩 이동하면서 (0~3 / 1~4 / 2~5) 해당 구간에 포함된 알파벳별 개수를 검사.
for (int i = w_cnt; i < s.size(); i++)
{
if (m2.find(s[i]) != m2.end()) // exist
{
m2[s[i]]++;
}
else
{ // non exist
m2[s[i]] = 1;
}
m2[s[i - w_cnt]]--;
//w, s에 대해 특정 구간안에 포함된 알파벳 구성이 같은지 검사
if (is_alph_consist_same(m, m2))
result++;
}
cout << result;
}
틀린 풀이
// https://www.acmicpc.net/problem/1593
#include <iostream>
#include <vector>
#include <string>
using namespace std;
int w_cnt, s_cnt;
string w, s;
int result;
// substr(시작위치, 갯수);
bool string_include(string word)
{
int n = word.size();
bool check = true;
for (int i = 0; i < s.size() - n; i++)
{
check = true;
for (int j = 0; j < n; j++)
{
if (s[i + j] != word[j])
{
check = false;
break;
}
}
if (check)
return true;
// if (s.substr(i, n) == word)
// {
// return true;
// }
}
return false;
}
void get_permutaion(string &origin_s, string &new_s, int dest_len, int cur_len)
{
if (cur_len == dest_len)
{
if (string_include(new_s))
{
result += 1;
}
return;
}
char cur_letter;
for (int i = 0; i < origin_s.size(); i++)
{
if (origin_s[i] == '1')
continue;
//현재 단어를 선택
cur_letter = origin_s[i];
origin_s[i] = '1';
new_s.push_back(cur_letter);
get_permutaion(origin_s, new_s, dest_len, cur_len + 1);
origin_s[i] = cur_letter;
new_s.pop_back();
}
}
int main()
{
ios_base::sync_with_stdio(false);
cin.tie(NULL);
cout.tie(NULL);
cin >> w_cnt >> s_cnt;
cin >> w;
cin >> s;
string new_w = "";
get_permutaion(w, new_w, w_cnt, 0);
cout << result;
}
심지어 처음에는 substr을 사용했는데, 더 느렸을 것 같다.....(/??????)
'알고리즘 > [문제풀이] BOJ' 카테고리의 다른 글
[BOJ] 20057 - 마법사 상어와 토네이도 (0) | 2021.10.15 |
---|---|
[BOJ] 5568 - 카드 놓기 (0) | 2021.10.04 |
[BOJ] 10804 - 나이순 정렬 (0) | 2021.10.02 |
[BOJ] 1717 - 집합의 표현 (0) | 2021.10.02 |
[BOJ] 3584 - 가장 가까운 공통 조상 (0) | 2021.10.01 |