Задача №857. Контрольная по ударениям
Разбор добавил Данияр Чумбалов
Для решения данной задачи рассмотрим действия, которые мы должны уметь выполнять:
1) Проверить данную строку на количество больших букв.
2) Узнать, существует ли в множестве строк (словаре) данная строка.
С 1), надеюсь, ни у кого трудностей не возникнет.
Однако насчет второго пункта следует подумать :
Максимальный размер словаря -- 20000 строк не более чем из 30 символов.
Суммарный объем проверяемого текста -- 300000 символов.
Понятно, что линейная проверка принадлежности каждого проверяемого слова словарю в конечном итоге
даст ошибку TL. Как же оптимизировать поиск данного слова в словаре?
Есть много способов оптимизации, вот 2 из них :
1) Для тех, кто пишет на Си -- это использование контейнера из библиотеки STl set.
2) Для тех, кто не пишет на Си -- это хэш-таблица.
Я приведу решение этой задачи, используя Сишный set.
Напомню, что все операции с set, производятся за время O(logN), где N -- это кол-во элементов в
set'е, а это лучше, чем O(N).
Чтобы не было путаницы, лучше завести 2 set'а для хранения словаря:
первый будет хранить множество строк -- это слова без ударений (для проверки принадлежности слова
словарю), а второй -- пару строк <слово_без_ударения, слово_с_правильным_ударением>.
set < string > dict; // set словарных слов без ударения
multiset < pair < string, string > > d_p; // set слов с ударениями (второй элемент pair)
Напишем функцию, которая строку с ударением превращает в строку без ударений (т.е. заменяет большие
буквы соответствующими маленькими).
// проверка символа, является ли он большой английской буквой.
bool big(char c)
{
if (c >= 65 && c <= 90) return true;
return false;
}
// сама функция
string convert(string s)
{
for (int i = 0; i < s.length(); i++)
if (big(s[i])) s[i] = s[i] + ('a' - 'A');
return s;
}
// в слове поставлено одно ударение?
bool check(string s)
{
int r = 0;
for (int i = 0; i < s.length(); i++)
if (big(s[i])) r++;
if (r == 1) return true;
return false;
}
Теперь заполним наш словарь :
int n; // общее кол-во строк
cin >> n;
string s;
for (int i = 0; i < n; i++){
cin >> s; // считываем строку
d_p.insert(make_pair(convert(s), s)); // добавляем пару -- слово без ударения и с ударением
dict.insert(convert(s)); // добавляем строку без ударения
}
int r = 0; // ответ обнуляем
while (cin >> s){ // пока не конец файла, считываем очередное слово
if (dict.find(convert(s)) == dict.end()){ // если такого слова нет в словаре
if (!(check(s))) r++; // то проверяем, сколько в нем больших букв
}else if (d_p.find(make_pair(convert(s), s)) == d_p.end()) r++; // если нашли такое слово
// проверяем правильность
// постановки ударения
}
cout << r; // выводим результат
С хэш-таблицей не должно возникнуть трудностей, т.к. решение с ней аналогичное.
Сдать: для сдачи задач необходимо войти в систему
3733
statement