문제
https://algospot.com/judge/problem/read/WILDCARD
걸린 시간
02 : 05 : 37 실패
풀이
C++
#include <stdio.h>
#include <iostream>
#include <vector>
#include <string.h> // memset
using namespace std;
#define INF 987654321
// -1 : 값이 계산되지 않음
// 1 : 해당 입력이 서로 대응됨
// 0 : 해당 입력들이 서로 대응되지 않음
int cache[101][101];
string W, S;
// 완전 탐색 O(N^3)
// wildcard 패턴 w가 문자열 s에 대응하는지 여부를 반환
bool matchMemoized(int w, int s){
int& ret = cache[w][s];
if(ret != -1){
return ret;
}
while(s < S.size() && w < W.size() && (W[w] == '?' || W[w] == S[s])){
s++;
w++;
}
/*
반복이 종료되는 경우
1. w[pos]와 s[pos]의 값이 다를 때
2. 패턴 w의 끝에 도달했을 경우
3. 문자열 s의 끝에 도달했을 경우
4. '*'를 만나서 종료
*/
// 2번, 패턴에 '*' 가 없었다는 뜻으로
if(w == W.size()){
// 문자열과 길이가 같다면 일치한다
return s == S.size();
}
// 4번, 패턴의 '*' 가 문자열의 어디까지 대응해야
// 할 지를 for 문을 통하여 확인
if(W[w] == '*'){
for(int skip = 0; s+skip <= S.size(); skip++){
if(matchMemoized(w+1, s+skip))
return ret = 1;
}
}
// 2, 4를 제외한 경우는 모두 대응되지 않음
return ret = 0;
}
int main(){
int tc;
scanf("%d", &tc);
while(tc--){
cin >> W;
vector<string> result;
int n;
scanf("%d", &n);
for(int i = 0; i < n; i++){
cin >> S;
memset(cache, -1, sizeof(cache));
if(matchMemoized(0, 0))
result.push_back(S);
}
sort(result.begin(), result.end());
for(int i = 0; i < result.size(); i++)
cout << result[i] << endl;
}
return 0;
}
조금 심화된 dp 문제를 풀어본 경험이 없어서일까 어떻게 부분 문제로 나누어 완전탐색을 해야 하는지 감이 오질 않았다.
종만북 풀이를 보고 하나하나 따라가 보았는데 복잡도를 O(n2) 까지 줄일 수 있는 최적의 분해방법까지는 이해하기가 어려웠다.
정답이 되기 위한 경우의 수를 따져보는 과정부터 재귀함수 구조를 설계하는 것 까지 스스로 생각하여 풀이하려면 정말 많은 문제를 풀어봐야겠다는 생각이 들었다.
'ALGOSPOT' 카테고리의 다른 글
algospot MATCHORDER 출전 순서 정하기 (0) | 2020.08.26 |
---|---|
algospot TSP1 여행하는 외판원 문제 1 (0) | 2020.08.23 |
algospot TRIANGLEPATH 삼각형 위의 최대 경로 (0) | 2020.08.20 |
algospot JUMPGAME 외발 뛰기 (0) | 2020.08.19 |
algospot FESTIVAL 록 페스티벌 (0) | 2020.08.19 |
댓글