вторник, 4 февраля 2014 г.

Подготовка к ЕГЭ. Задача C4: анализ строк

Вам необходимо написать программу анализа текста. На вход программе подаются строки, содержащие английские слова. В одной строке может быть произвольное количество слов. Все слова записаны строчными (маленькими) английскими буквами. Между словами в строке может быть один или больше пробелов, возможны пробелы в начале и в конце строки. Других символов, кроме строчных английских букв и пробелов, в строках нет. Длина каждой строки не превышает 200 символов. Количество строк неизвестно, общее количество слов не более одного миллиона. Конец ввода обозначается строкой, содержащей единственный символ «*».
Напишите эффективную, в том числе по памяти, программу, которая будет определять количество слов, начинающихся на каждую букву английского алфавита, и выводить эти количества и соответствующие им буквы в порядке убывания. Если количество слов, начинающихся на какие-то буквы, совпадает, эти буквы следует выводить в алфавитном порядке. Если на какую-то букву слов нет, выводить эту букву не надо.
Размер памяти, которую использует Ваша программа, не должен зависеть от размера исходного списка.

Перед текстом программы кратко опишите используемый Вами алгоритм решения задачи и укажите используемый язык программирования и его версию.

Пример входных данных: 
 one two three four five 
    a quick brown fox
*
Пример выходных данных для приведенного выше примера входных данных: 
f 3 
t 2 
а 1 
b 1 
о 1
q 1

Примечание. Английский алфавит совпадает с латинским и содержит 26 букв от а до z:
abcdefghijklmnopqrstuvwxyz
(Источник: kpolyakov.spb.ru)

Решение

Начало слова в строке характеризуется последовательностью из двух символов: пробел и буква. Так что для подсчета первых букв слов надо подсчитать символы, стоящие после пробелов, а также первый символ в строке (в том случае, если он не пробел) 
Массив sum[1..26] будет хранить частоту вхождения букв в строках, а массив letters - соответствующие буквы.
При нахождении буквы, которая является началом слова, нужно увеличить на 1 элемент sum[i], где i - порядковый номер буквы в английском алфавите.
После того, как считаны и обработаны все строки, синхронно сортируем массивы sum и letters по убыванию значений в массиве sum.
Выведем на экран только ненулевые значения массива sum и соответствующие значения массива letters.

program c4;

{ delta - разница между порядковым номером буквы в английском алфавите и ее кодом в таблице ASCII}
const delta = ord('a')-1;

var sum: array[1..26] of integer;
    letters: array[1..26] of char;
    s:string;
    i,j,k,tmp:integer;
    c:char;

begin
 // инициализируем массивы в массив
 for i:=1 to 26 do
 begin
     sum[i] := 0;
     letters[i] := chr(ord(i)+delta);
 end;
 s:='';
 while s<>'*' do
 begin
    // Дополняем строку пробелом спереди. 
    // Так мы можем не проверять отдельно первый символ.
    s := ' '+s;
    for i:=1 to length(s)-1 do
    begin
       // Проверка начала слова
       if (s[i]=' ') and (s[i+1]<>' ') then
          inc(sum[ord(s[i+1])-delta]);
    end;
    // Считываем следующую строку
    readln(s);
 end;
 // Сортируем пузырьком синхронно два массива: частот и букв
 // Критерий сортировки: по убыванию частот
 for k:=1 to 26 do
     for j:=1 to 26-k do
     begin
        if sum[j]<sum[j+1] then
        begin
           tmp:=sum[j];
           sum[j]:=sum[j+1];
           sum[j+1]:=tmp;
           c:=letters[j];
           letters[j]:=letters[j+1];
           letters[j+1]:=c;
        end;
     end;
 i:=1;
 // Выводим все ненулевые элементы массива
 for i:=1 to 26  do
 begin
     if sum[i]>0 then
        writeln(letters[i],' ', sum[i]);
 end;
 readln;
end;

Комментариев нет:

Отправить комментарий