Wildcard
어떻게 풀까?
가장 까다로운 부분은 바로 '*' 부분입니다.
'*'은 몇 개의 글자도 커버할 수 있기 때문입니다.
몇 개의 글자를 커버할지 모르기 때문에, '*'가 나온다면, '*'가 커버하는 글자를 하나씩 증가시키면서 문제를 생각해봅시다.
예를들면,
*p*와 help를 비교할 때,
처음에는 *에 글자가 0개 들어간다고 가정하고,
다음에는 h 하나, 그 다음에는 he, 그 다음에는 hel을 넣는 것입니다.
예제에서는 hel에서 매칭이 된다고 나오겠지만, 만약 hel 에서도 답이 나오지 않는다면, *에 help까지 넣어보는 것입니다.
하지만, 이 때 큰 문제가 생깁니다.
만약 문제가 *a*a이고,
aaaaa12345 가 맞는지 매칭을 시도하면 중복해서 계산하는 경우가 생기는 것입니다.
예를 들면, 처음 '*'에는 아무것도 매칭시키지 않고, 2번째 '*'에는 1 까지를 매칭시켰다고 합시다.
다음에 처음 '*'에 a나 aa, aaa를 매칭시켜도 2번째 '*' 부분 1 까지 매칭시켜서 확인할 때 중복으로 계산함을 볼 수 있습니다.
따라서, 이를 위해 '몇 번째 문자열에 몇 번째 와일드카드까지 매칭했다.' 라는 정보를 담고있는 별도의 저장 공간을 만들도록 하겠습니다.
이렇게 하면, '*'가 1에 매칭 됐던 적이 있고, 이 값이 false이기 때문에 어짜피 매칭 해도 안된다는 것을 쉽게 알 수 있습니다.
마지막으로, 답을 출력할 때 문자열을 정렬할 필요가 있는데, 이는 적절한 정렬 알고리즘을 사용합시다.
저는 병합 정렬을 직접 구현했습니다.
코드
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 | //와일드 카드 //알고스팟 //https://algospot.com/judge/problem/read/WILDCARD #pragma once #include<cstring> #include<cstdio> int check[100][100]; int len[51]; char str[51][101]; int n, t; int strRes[50]; int temp[50]; int rIdx; void init() { scanf("%s\n", str[0]); scanf("%d\n", &n); for (int i = 1; i <= n; i++) { scanf("%s\n", str[i]); } for (int i = 0; i <= n; i++) { len[i] = strlen(str[i]); } rIdx = 0; } bool match(int sIdx, int sLen, int wLen) { if (sLen == len[sIdx] && wLen == len[0]) { return true; } else if (sLen > len[sIdx] || wLen > len[0]) return false; if (check[sLen][wLen] != -1) return check[sLen][wLen]; int ret = check[sLen][wLen]; if (str[0][wLen] == '*') { return ret = match(sIdx, sLen, wLen + 1) || match(sIdx, sLen + 1,wLen); } if (str[0][wLen] != '?' && str[0][wLen] != str[sIdx][sLen]) { check[sLen][wLen] = false; return false; } else { return check[sLen][wLen] = match(sIdx, sLen + 1, wLen + 1); } return false; } void merge(int left, int half, int right) { int l = left, r = half + 1, k = left; while (l <= half && r <= right) { if (strcmp(str[strRes[l]], str[strRes[r]]) > 0) { temp[k++] = strRes[r++]; } else { temp[k++] = strRes[l++]; } } while (l <= half) temp[k++] = strRes[l++]; while (r <= right) temp[k++] = strRes[r++]; for (int i = left; i <= right; i++) { strRes[i] = temp[i]; } } void mergeSort(int left, int right) { if (left < right) { int half = (left + right) / 2; mergeSort(left, half); mergeSort(half + 1, right); merge(left, half, right); } } int main() { scanf("%d\n", &t); while (t--) { init(); for (int i = 1; i <= n; i++) { memset(check, -1, sizeof(check)); bool res = match(i, 0, 0); if (res) { strRes[rIdx++] = i; } } mergeSort(0, rIdx - 1); for (int i = 0; i < rIdx; i++) { printf("%s\n", str[strRes[i]]); } } return 0; } | cs |
'공부 > 알고리즘 문제풀이' 카테고리의 다른 글
[알고스팟] 최장 증가 부분 수열 LIS (longest increasing subsequence) (0) | 2018.06.14 |
---|---|
[알고스팟] 삼각형 위의 최대 경로 (0) | 2018.06.12 |
[알고스팟] 외발 뛰기 (0) | 2018.06.12 |
[알고스팟] 팬 미팅 (0) | 2018.06.11 |
[알고스팟] 울타리 잘라내기 (0) | 2018.06.11 |