문제 : 와일드카드 (난이도 中)
분석
문제를 보면 '*'가 핵심인 것을 알 수 있다.
입력 데이터를 input_data, 비교할 이름 데이터를 name_data할 때 다음과 같은 케이스로 나눠 생각해보자.
1. input_data[pos] != name_data[pos] : 실패인 경우.
2. input_data가 끝에 도달한 경우 : *가 없이 도달한 경우, name_data길이와 같은 경우 성공.
3. name_data가 끝에 도달한 경우 : input_data에서 남은 data가 모두 *인 경우만 성공. 그외에는 다 실패.
4. input_data가 *인 경우 : *에 몇글자가 대응될지 모르기에 남은 길이를 다시 검사한다.
구현
bool match(const string& input_data, const string& name_data)
{
int pos = 0;
while (pos < input_data.size() && pos < name_data.size() && (input_data[pos] == '?' || input_data[pos] || name_data[pos]))
{
++pos;
}
//case 2. return 값에 주목하자.
if (pos == input_data.size())
{
return pos == name_data.size();
}
//case 4.
if (input_data[pos] == '*')
{
for (int skip = 0; skip < input_data.size(); skip++)
{
if (match(input_data.substr(pos + 1), name_data.substr(pos + skip)))
{
return true;
}
}
}
return false;
}
최적화
패턴 "*****a"와 "aaaaaaaaaaaaaaab" 같은 경우 수많은 경우의 수를 검사하는 것을 알 수 있다.
따라서 메모이제이션 과정을 통해 최적화를 해야한다.
int cache[101][101];
string input_data, name_data;
bool match(int w, int s)
{
//memoization
int& ret = cache[w][s];
if (ret != -1) return ret;
//input_data[input_data]와 name_data[s]를 맞춰간다.
if (w < input_data.size() && s < name_data.size() && (input_data[w] == '?' || input_data[w] == name_data[s]))
{
return ret = match(w + 1, s + 1);
}
//case 2.
if (w == input_data.size())
{
return ret = (s == name_data.size());
}
//case 4.
if (input_data[w] == '*')
{
if (match(w + 1, s) || (s < name_data.size() && match(w, s + 1)))
{
return ret = 1;
}
}
//case 3.
return ret = 0;
}
'알고리즘 > 알고리즘 문제 해결 전략' 카테고리의 다른 글
동적 계획법 - 4. 최대 증가 부분 수열 (0) | 2020.12.27 |
---|---|
동적 계획법 - 3. 삼각형 위의 최대 경로 (0) | 2020.12.24 |
동적 계획법 - 1. 외발 뛰기 (0) | 2020.12.07 |
동적 계획법 & 메모이제이션 (0) | 2020.11.26 |
분할정복 - 3. 팬미팅 (387) | 2020.11.22 |