Матч 6, Сравнение с шаблоном (WildCard)

 

Строка file содержит имя файла. Его необходимо преобразовать в строку pattern, которая может содержать символы-джокеры ‘?’ (один любой символ). Необходимо найти наименьшее количество операций вставки, удаления или переименования символа, выполнение которых преобразовывают file в pattern.

 

Класс: WildCardMatch

Метод: int minimalChanges(string file, string pattern)

Ограничения: file и pattern содержат от 1 до 50 символов ‘a’ – ‘z’, строка pattern может содержать символы-джокеры ‘?’.

 

Вход. Две  строки file и pattern.

 

Выход. Наименьшее количество операций вставки, удаления или переименования символа, преобразовывающих file в pattern.

 

Пример входа

file

pattern

"abcd"

"bcd"

"aaaabbb"

"aa????b"

"asdjkhajksdhajksdh"

"asdjkhasdjk?"

"niceone"

"ieo?e"

 

Пример выхода

1

0

6

2

 

 

РЕШЕНИЕ

динамическое программирование

 

Пусть f[i][j] содержит наименьшее количество преобразований, которые переводят file[0..i] в pattern[0..j]. Для удобства кодирования допишем в начало обоих слов символ ‘0’. От этого искомое количество операций не изменится, однако число преобразований file[0..i] в pattern[0..j] будет храниться в f[i + 1][j + 1]. После дописывания нулей перед строками нулевым индексам массива f соответствуют пустые строки. f[0][0]  = 0 соответствует тому, что для преобразования пустой строки в пустую требуется 0 операций. f[0][j] будет хранить наименьшее количество операций, переводящих пустую строку (“”) в pattern[0..j – 1]. Занесем во все ячейки массива f значение µ. Рассмотрим, как вычислить значение f[i + 1][j + 1] по известным f[i1][j1], 0 £ i1 £ i, 0 £ j1 £ j:

·  если file[i] = pattern[j] или pattern[j] = '?', то f[i + 1][j + 1] = f[i][j];

·  если i - ый символ file и j - ый символ pattern не совпадают, то возможно одно из трех преобразований. Причем производить следует то преобразование, после выполнения которого f[i + 1][j + 1] с наименьшим, а именно:

·  если file[i] заменить на pattern[j], то f[i + 1][j + 1] = f[i][j] + 1;

·  если символ file[i] удалить, то f[i + 1][j + 1] = f[i][j + 1] + 1;

·  если символ pattern[j] вставить, то f[i + 1][j + 1] = f[i + 1][j] + 1;

Объединив приведенные условия, получим:

f[i + 1][j + 1] =

min( min( 1 + f[i][j + 1], 1 + f[i + 1][j]), (!((file[i] = = pattern[j]) || (pattern[j] = = ‘?’))) + f[i][j]),

f[0][0] = 0.

 

 

ПРОГРАММА

 

#include <cstdio>

#include <string>

#include <memory>

using namespace std;

 

int f[51][51];

 

class WildCardMatch

{

public:

  int minimalChanges(string file, string pattern)

  {

    int i,j;

    memset(f,63,sizeof(f));f[0][0] = 0;

    file = "0" + file; pattern = "0" + pattern;

    for(i=0;i<file.size();i++)

      for(j=0;j<pattern.size();j++)

        f[i+1][j+1] = min(min(1+f[i][j+1],1+f[i+1][j]),

              (!((file[i] == pattern[j]) || (pattern[j] == '?')))+f[i][j]);

    return f[file.size()][pattern.size()];

  }

};