![]() |
|
|
Регистрация | << Правила форума >> | FAQ | Пользователи | Календарь | Поиск | Сообщения за сегодня | Все разделы прочитаны |
![]() |
|
Опции темы | Поиск в этой теме | Опции просмотра |
#1
|
|||
|
|||
![]() Программа для N равного 1000 работает 7 секунд, надо 2. Входной текстовый файл большой 1МБ.
Код:
program Project2; {$APPTYPE CONSOLE} {$R+,Q+,I+} uses SysUtils; const a='а'; const Wmin =1000; const ABC=['а'..'я', 'А'..'Я','ё','Ё']; Function EqualWord(n:string; w: array of string; i:integer):boolean; //проверяет выходном массиве w есть ли такое слово n var l:integer; begin result:=true; for l:=1 to i do if ansilowercase(w[l])=ansilowercase(n) then result:=false; end; Function ShortestWord (w:string;z:array of string; k:integer):boolean; // Проверяет есть ли в массиве z cлова которые длиннее входного слова w var i:integer; begin Result:=false; if z[1]='' then result:=true; for i:=k downto 1 do if length(z[i])>length(w) then begin Result:=true; exit; end; end; Procedure InsertWord(w:string;var z:array of string; var k:integer); // проверяем куда нам нужно вставить слово w и вставляет по неубыванию длины var prev,d:string; i:integer; begin prev:=w; for i:=k downto 1 do begin if length(z[i])<length(prev) then begin d:=z[i]; z[i]:=prev; z[i+1]:=d; end; end; end; Function Letter(w:string;a:char):boolean; // Проверяет содержит ли слово два раза заданную букву var i,j : integer; begin j:=0; Result:=false; for i:=1 to length(w) do if w[i]=a then inc(j); If j=2 then result:=true; end; {#34.Дан файл, содержащий русский текст. Найти в тексте N<=2000 самых коротких слов, содержащих 2 раза заданную букву. Записать найденные слова в текстовый файл в порядке неубывания длины. Все найденные слова должны быть разными!} var i,j,k : integer; s:string; z: array [1..2000] of string;//массив найденных слов w: array [1..100] of string; //массив слов теущей строки begin rewrite (output, 'output.txt'); reset (input, 'input.txt'); while not seekeof do begin readln(s); s:=s+' '; i:=1; j:=0; while i<=length(s) do begin if s[i] in ABC then begin inc(j); w[j]:=''; while s[i] in ABC do begin w[j]:=w[j]+s[i]; inc(i); end; inc(i); end else inc (i); end; k:=Wmin; for i:=1 to j do begin if (Letter(w[i],a)) and (EqualWord(w[i],z,k)) and (ShortestWord(w[i],z,k)) then InsertWord(w[i],z,k); end; end; for i:=1 to Wmin do If z[i]<>'' then writeln (z[i],' '); end. |
#2
|
|||
|
|||
![]() У меня сомнения, что эта программа вообще работает... Оптимизировать здесь много чего можно, для начала выходить с циклов, когда условие удовлетворено, а не крутить их до посинения. А вообще пересмотреть алгоритм и проделать все тоже самое, только в одном цикле.
Последний раз редактировалось Asinkrit, 05.01.2011 в 19:23. |
#3
|
||||
|
||||
![]() Тут нечего оптимизировать - нужно заново писать программу.
Просто ты её начал решать прямолинейно, а нужно было чуток схитрить. |
#4
|
|||
|
|||
![]() В общем, +1 к предыдущим постам.
а если тупо оптимизировать текущую версию, то: 1. Отказаться от динамических массивов типа String - использовать TStringList. 2. Выходы из циклов при выполнении условия (уже упоминалось). 3. Минимизировать кол-во операций со строками (upper/lower) путем того, что добавлять в список уже обработынные априори строки. тогда в сравнении тебе надо будет преобразовывать одну строку, а не обе. Плюс к этому вынести преобразование за границы цикла. 4. читать исходный файл одним куском в тот же TStringList. 5. Использовать глобальные переменнные там, где это имеет смысл. Вот этот список - для начала. |
#5
|
|||
|
|||
![]() Мой вариант кода на проце Core 2 Duo (мобильном) под WinXP файл размером 795.207 байт (взял текст какой-то книжки с lib.rus.ec) отрабатывает меньше, чем за секунду для N = 1000.
|