반응형
문제 설명
algospot.com :: WILDCARD
Wildcard 문제 정보 문제 와일드카드는 다양한 운영체제에서 파일 이름의 일부만으로 파일 이름을 지정하는 방법이다. 와일드카드 문자열은 일반적인 파일명과 같지만, * 나 ? 와 같은 특수 문자를
www.algospot.com
- 와일드카드 문자열 W가 주어진다.
- N개의 파일명이 주어진다.
- 파일명은 알파벳 대소문자, 숫자로 이루어져 있으며, 와일드카드는 * 와 ? 도 가질 수 있다.
- ? 는 해당 자리에 어떤 문자가 와도 된다.
- *는 해당 자리에 0글자 이상의 어떤 문자들이 와도 된다.
=> 와일드 카드에 매치되는 파일명들을 아스키 코드 순서대로 출력하기
문제 풀이
재귀함수를 이용해 와일드 카드와 각 파일명을 한글자씩 비교하는데,
와일드카드의 각 글자가 무엇인지에 따라 3가지 경우로 나눌 수 있다.
- 알파벳이나 숫자일 경우(기호가 아닌 문자일 경우)
- ? 일 경우
- * 일 경우
1번의 경우와 2번의 경우는 각 글자를 1:1로 비교하면 된다.
하지만 3번, *일 경우가 문제인데, *의 자리에는 0글자 이상의 어떤 문자가 와도 되므로
- 자리에 아무것도 없을 경우
- *자리에 문자가 더 있을 경우
- *자리에 문자가 더이상 없을 경우
이러한 3가지 경우로 또 나뉘어진다.
이 때, *일 경우에 나뉘는 3가지 경우는 연산 중복이 발생할 수 있기 때문에
메모이제이션을 이용하여 각 인덱스를 비교했을때의 결과를 저장하여 재사용한다.
문제 풀이 코드
#include <iostream>
#include <string.h>
#define MAXSIZE 100;
using namespace std;
int N;
char W[101];
char Cards[50][101];
char SortedCardIndexes[50][101];
char Answers[50][101];
int ansCnt;
int memoization[101][101];
int checkString(int order, int wIndex ,int cardIndex) {
if (memoization[wIndex][cardIndex] != -1) return memoization[wIndex][cardIndex];
int result = 0;
// 둘 다 끝에 도달했을 경우이거나, 와일드카드의 끝이 *일 경우
if ((W[wIndex] == '\0' && Cards[order][cardIndex] == '\0') || (W[wIndex] == '*' && W[wIndex + 1] == '\0'))
result = 1;
else if (W[wIndex] == '\0' || Cards[order][cardIndex] == '\0')
result = 0;
else if (W[wIndex] == '*')
// * 자리에 아무것도 없을 경우 + * 자리에 문자가 더 있을 경우 + * 자리에 글자가 더이상 없을 경우
result = checkString(order, wIndex + 1, cardIndex) + checkString(order, wIndex, cardIndex + 1) + checkString(order, wIndex + 1, cardIndex + 1);
else if (W[wIndex] == '?')
result = checkString(order, wIndex + 1, cardIndex + 1);
else if (W[wIndex] == Cards[order][cardIndex])
result = checkString(order, wIndex + 1, cardIndex + 1);
memoization[wIndex][cardIndex] = result;
return result;
}
int compare(char* str1, char* str2) {
int index = 0;
while (index <= 100) {
if (str1[index] == str2[index])
++index;
else
return str1[index] - str2[index];
}
}
void merge(int left, int mid, int right) {
int i = left;
int j = mid + 1;
int k = left;
while (i <= mid && j <= right) {
if (compare(Answers[i], Answers[j]) < 0) {
memcpy(&SortedCardIndexes[k++], &Answers[i++], 101);
}
else {
memcpy(&SortedCardIndexes[k++], &Answers[j++], 101);
}
}
while (i <= mid) {
memcpy(&SortedCardIndexes[k++], &Answers[i++], 101);
}
while (j <= right) {
memcpy(&SortedCardIndexes[k++], &Answers[j++], 101);
}
for (int l = left; l <= right; ++l) {
memcpy(&Answers[l], &SortedCardIndexes[l], 101);
}
}
void merge_sort(int left, int right) { // 머지 소트(합 정렬)
int mid;
if (left < right) {
mid = (left + right) / 2;
merge_sort(left, mid);
merge_sort(mid + 1, right);
merge(left, mid, right);
}
}
int main() {
int C;
cin >> C;
for (int tc = 1; tc <= C; ++tc) {
memset(W, '\0', 101);
memset(Cards, '\0', 50 * 101);
memset(Answers, '\0', 50 * 101);
ansCnt = 0;
cin >> W;
cin >> N;
for (int i = 0; i < N; ++i) {
cin >> Cards[i];
}
for (int i = 0; i < N; ++i) {
memset(memoization, -1, 101 * 101 * sizeof(int)); // 메모이제이션 초기화
bool result = checkString(i, 0, 0); // 문자열 비교
if (result > 0)
memcpy(Answers[ansCnt++], Cards[i], 101); // 답이면 정답 배열에 copy
}
merge_sort(0, ansCnt - 1); // 아스키 코드 순으로 정렬
for (int i = 0; i < ansCnt; ++i) {
cout << Answers[i] << endl;
}
}
return 0;
}
반응형
'알고리즘 문제풀이 > 알고리즘 문제해결전략' 카테고리의 다른 글
8.7_원주율 외우기_PI (0) | 2023.02.13 |
---|---|
8.5_합친 LIS_JLIS (0) | 2023.02.12 |
7.3_울타리 잘라내기_FENCE (0) | 2023.02.08 |
7.2_쿼드 트리 뒤집기_QUADTREE (0) | 2023.02.07 |
6.8_시계 맞추기_CLOCKSYNC (0) | 2023.01.20 |