2020.02.17
풀이
- 기본적으로 input1, input2를 입력받으면서 바로 비교하도록 함수를 구현하였고 비교해서 조건을 만족하면 결과 벡터에 푸시하였다. 마지막으로 compare와 함께 결과를 sort 해서 출력하였다.
- *, ?, 문자 경우를 나누어 재귀함수를 이용해 idx1,idx2를 증가, 그대로 두며 완전탐색하도록 만들었다.
- 동적계획법 문제인데 먼저 완전탐색으로 확인하여 시간초과가 나면 DP를 어떻게 적용할지 고려해보려 했는데 시간초과없이 통과해버렸다..
코드
//! 2020.02.17
// TODO AS_WILDCARD
// Brute Force (Dynamic Programming)
#include<iostream>
#include<string>
#include<vector>
#include<algorithm>
using namespace std;
int C, N;
vector <string> result;
int sizeStr;
string input1;
string input2;
bool compare(string s1, string s2) {
if (s1.compare(s2) < 0) return true;
else return false;
}
bool getResult(int idx1,int idx2) {
if (idx1 >= input1.length()) {
if(idx2 >= input2.length()) return true;
else return false;
}
else {
if (input1[idx1] == '*'){
if (idx2 >= input2.length()) return getResult(idx1+1,idx2);
else return getResult(idx1 + 1, idx2 + 1) || getResult(idx1, idx2 + 1) || getResult(idx1 + 1, idx2);
}
else{
if (idx2 >= input2.length()) return false;
else if (input1[idx1] == '?') return getResult(idx1 + 1, idx2 + 1);
else if (input1[idx1] == input2[idx2]) return getResult(idx1 + 1, idx2 + 1);
else return false;
}
}
}
int main() {
cin >> C;
for (int c = 0; c < C; c++) {
cin >> input1;
cin >> N;
for (int n = 0; n < N; n++) {
cin >> input2;
//cout << input1 << endl << input2 << endl;
if (getResult(0,0)) result.push_back(input2);
}
//printf("%d\n", result[0].compare(result[1]));
sort(result.begin(), result.end(), compare);
//cout << "my results!!!" << endl;
for (int i = 0; i < result.size(); i++) {
cout << result[i] << endl;
}
vector <string> empty;
result.swap(empty);
}
return 0;
}
실수
* 일때 idx2 를 증가시키거나 idx1와 함께 증가시키거나 두가지 경우만 탐색했었다. 하지만 idx1만 증가하는 경우도 있었고 이를 고려해서 해결하였다.
메모이제이션 활용
idx1, idx2를 각각 증가시키면서 매칭을 시도할 때, *로 인해 결국 idx1부터 끝까지, idx2부터 끝까지를 재귀함수가 비교하게 된다.
이 때, 한번 구했던 결과는 다른 * 혹은 다른 문자에서 비교한다고 해도 같은 결과다.
결국 같은 비교를 여러번 하게 된다는 의미이다.
즉, 알고리즘 상 O(N^2) 으로 비교할 수 있는 데, 여러번 반복하기 때문에 *의 갯수만큼 더 비교하게 되고 최악의 경우 O(N^3)에 가깝게 시간복잡도가 늘어날 수 있다.
메모이제이션을 통해 이를 막을 수 있었고, 196ms 를 4ms로 줄일 수 있었다.
코드
//! 2020.02.17
// TODO AS_WILDCARD
// Brute Force (Dynamic Programming)
#include<iostream>
#include<string>
#include<vector>
#include<algorithm>
using namespace std;
const int MAX = 105;
int C, N;
vector <string> result;
int sizeStr;
string input1;
string input2;
int DP[MAX][MAX];
bool compare(string s1, string s2) {
if (s1.compare(s2) < 0) return true;
else return false;
}
bool getResult(int idx1, int idx2) {
int& ret = DP[idx1][idx2];
if (ret != -1) return ret;
if (idx1 >= input1.length()) {
if (idx2 >= input2.length()) return ret = 1;
else return ret = 0;
}
else {
if (input1[idx1] == '*') {
if (idx2 >= input2.length()) return ret = getResult(idx1 + 1, idx2);
else return ret = getResult(idx1 + 1, idx2 + 1) || getResult(idx1, idx2 + 1) || getResult(idx1 + 1, idx2)? 1:0;
}
else {
if (idx2 >= input2.length()) return ret = 0;
else if (input1[idx1] == '?') return ret = getResult(idx1 + 1, idx2 + 1);
else if (input1[idx1] == input2[idx2]) return ret = getResult(idx1 + 1, idx2 + 1);
else return ret = 0;
}
}
}
void resetDP(int rows, int cols) {
for (int i = 0; i < rows; i++) {
for (int j = 0; j < cols; j++) {
DP[i][j] = -1;
}
}
}
int main() {
resetDP(MAX, MAX);
cin >> C;
for (int c = 0; c < C; c++) {
cin >> input1;
cin >> N;
for (int n = 0; n < N; n++) {
cin >> input2;
//cout << input1 << endl << input2 << endl;
if (getResult(0, 0)==1) result.push_back(input2);
resetDP(input1.length()+1, input2.length()+1);
}
//printf("%d\n", result[0].compare(result[1]));
sort(result.begin(), result.end(), compare);
//cout << "my results!!!" << endl;
for (int i = 0; i < result.size(); i++) {
cout << result[i] << endl;
}
vector <string> empty;
result.swap(empty);
}
return 0;
}
'SW > 알고리즘 문제풀이' 카테고리의 다른 글
백준17135 캐슬디펜스 (0) | 2020.02.18 |
---|---|
ALGOSPOT TRIANGLEPATH (0) | 2020.02.17 |
백준1918 후위 표기식 (0) | 2020.02.17 |
백준17070 파이프 옮기기 1 (0) | 2020.02.17 |
백준17406 배열돌리기4 (0) | 2020.02.16 |
Comment