IPB
ЛогинПароль:

> Прочтите прежде чем задавать вопрос!

1. Заголовок темы должен быть информативным. В противном случае тема удаляется ...
2. Все тексты программ должны помещаться в теги [code=pas] ... [/code], либо быть опубликованы на нашем PasteBin в режиме вечного хранения.
3. Прежде чем задавать вопрос, см. "FAQ", если там не нашли ответа, воспользуйтесь ПОИСКОМ, возможно такую задачу уже решали!
4. Не предлагайте свои решения на других языках, кроме Паскаля (исключение - только с согласия модератора).
5. НЕ используйте форум для личного общения, все что не относится к обсуждению темы - на PM!
6. Одна тема - один вопрос (задача)
7. Проверяйте программы перед тем, как разместить их на форуме!!!
8. Спрашивайте и отвечайте четко и по существу!!!

 
 Ответить  Открыть новую тему 
> подсчет слов в Trie дереве
сообщение
Сообщение #1


Новичок
*

Группа: Пользователи
Сообщений: 22
Пол: Мужской

Репутация: -  0  +


Добрый день. Помогите пожалуйста с задачей: в Trie дереве подсчитать количество слов, в которых имеется буква "а" (все буквы маленькие, латинские).

Собственно, проблема в написании одной процедуры - поиска слова с заданной буквой. Описание, создание, печать и другие нужные мне процедуры написал. Прилагаю код:

unit Unit1;
interface
 type
 TIndex='a'..'z';
 TrieTree=^TNode;
 TNode=record
        Ptrs:array [TIndex] of TrieTree;
        eow:boolean;
       end;
 TTrieTree=object
           private
            TTree:TrieTree;
           public
            constructor Init;
            function Empty:boolean;
            procedure Push(s:string);
            function find(s:string):boolean;
            procedure pop(s:string);
            procedure print;
            procedure clear;
            destructor done; virtual;
end;

implementation
Constructor TTrieTree.Init;
begin
 TTree:=nil;
end;

function TTrieTree.Empty;
begin
 Empty:=TTree=nil
end;

Procedure TTrieTree.Push(s:string);
 Procedure PushString(var T:TrieTree; i:byte);
 var ch:TIndex;
 begin
  if t=nil then
   begin
    new(t);
    T^.eow:=false;
    for ch:=low(Tindex) to High(Tindex) do
     T^.Ptrs[ch]:=nil;
   end;
  if length(s)<i then
   t^.eow:=true
  else
   PushString(T^.Ptrs[s[i]],i+1)
 end;
begin
 if Length(s)>0 then pushstring(TTree,1)
end;

function TTrieTree.find(s:string):boolean;
 function FindString(T:TrieTree; i:byte):boolean;
 var ch:TIndex;
 begin
  if T=nil then
   FindString:=false
  else
   if Length(s)<i then
    FindString:=T^.eow
   else
    FindString:=FindString(T^.Ptrs[s[i]],i+1)
 end;
begin
 if Length(s)=0 then
  Find:=false
 else
  Find:=FindString(TTree,1)
end;

Procedure TTrieTree.pop(s:string);
function AllEmpty(T:TrieTree):boolean;
var ch:TIndex; fl:boolean;
begin
 fl:=not T^.eow;
 ch:=Low(TIndex);
 while (ch<=High(TIndex)) and fl do
  if T^.Ptrs[ch]=nil then
   ch:=succ(ch)
  else
   fl:=false;
  AllEmpty:=fl;
end;

Procedure PopString(var T:TrieTree; i:byte);
var ch:TIndex;
begin
 if (t<>nil) then
  if i<=length(s) then
   PopString(t^.Ptrs[s[i]],i+1)
  else
   begin
    T^.eow:=false;
    if allempty(t) then
     begin
      dispose(t);
      T:=nil;
     end;
   end;
end;

begin
 if length(s)>0 then
  PopString(TTree,1);
end;

Procedure TTrieTree.print;
procedure PrintString(T:TrieTree; s:string);
var ch:TIndex;
begin
 if t^.eow then
  writeln(s);
 for ch:=Low(Tindex) to High (TIndex) do
  if t^.Ptrs[ch]<>nil then
   begin
    if ch='a' then writeln('!!!');
    PrintString(T^.Ptrs[ch],s+ch);
   end;
end;
begin
 if not Empty then
  PrintString(TTree,'')
 else
  writeln('Tree is empty');
end;

procedure TTrieTree.clear;
procedure delNodes(var T:TrieTree);
var ch:TIndex;
begin
 for ch:=Low(Tindex) to High(Tindex) do
  if T^.Ptrs[ch] <> nil then
   DelNodes(T^.Ptrs[ch]);
  dispose(t);
  t:=nil;
end;
begin
 if not Empty then DelNodes(TTree);
end;

destructor TTrieTree.done;
begin
 if TTree<>nil then Clear;
end;

end.


Сообщение отредактировано: redeezko -
 Оффлайн  Профиль  PM 
 К началу страницы 
+ Ответить 
сообщение
Сообщение #2


Гость






Примерно так:

procedure Find(LastLetter: char; T: PNode; C: char);
var
  i: char;
begin
  if (T <> nil) and (T^.eow) then begin 
    if LastLetter = C then 
      WriteAllChilds(T)
    else
      for i := Low(T^.Ptrs) to High(T^.Ptrs) do Find(i, T^.Ptrs[i], C);
  end;
end;


Только названия типам и полям дай нормальные, например, такие:

TIndex='a'..'z';
 PNode=^TNode; // стандартно для указателя просто заменяют в начале T на P
 TNode=record
        Ptrs:array [TIndex] of PNode;
        eow:boolean;
       end;
 TTrieTree=object
           private
            Node:PNode;
   ...

 К началу страницы 
+ Ответить 
сообщение
Сообщение #3


Новичок
*

Группа: Пользователи
Сообщений: 22
Пол: Мужской

Репутация: -  0  +


Спасибо большое за ответ =). Но непонятно LastLetter - это что за параметр? Что им будет в программе, при вызове
данной процедуры?
 Оффлайн  Профиль  PM 
 К началу страницы 
+ Ответить 
сообщение
Сообщение #4


Гость






LastLetter - это как бы индекс данного узла по отношению к родителькому массиву. При первом вызове надо в качестве него написать что-то, не являющееся C. Да, фигня какая-то.

Лучше сделать его boolean.
То есть лучше так:

procedure Find(LastLetter_is_C: boolean; T: PNode; C: TIndex);
var
  i: TIndex;
begin
  if (T <> nil) and (T^.eow) then begin 
    if LastLetter_is_C then 
      WriteAllChilds(T)
    else
      for i := Low(T^.Ptrs) to High(T^.Ptrs) do Find(i=C, T^.Ptrs[i], C);
  end;
end;


А при первом вызове делать его False.
 К началу страницы 
+ Ответить 
сообщение
Сообщение #5


Новичок
*

Группа: Пользователи
Сообщений: 22
Пол: Мужской

Репутация: -  0  +


Что то не получается...
Вставил в свой код данную процедуру вот таким образом:
procedure TTrieTree.sum;
procedure findletter(f:boolean; T:TrieTree; c:TIndex);
var i:TIndex;
begin
 if (t<>nil) and (t^.eow) then
  begin
   if f then
    writeln('!!!') //здесь должно быть увеличение счетчика, но пока поставил это для тестирования
   else
    for i:=Low(T^.Ptrs) to High(T^.Ptrs) do
      findletter(i=c,t^.ptrs[i],c);
  end;
end;
var flag:boolean; c:char;
begin
 flag:=false;
 c:='a';
 findletter(flag,TTree,c);
end;


При пошаговом выполнении данной процедуры в программе, компилятор доходит до строки
f (t<>nil) and (t^.eow) then

и завершает работу данной процедуры. Если заменить and на or, то она выполняется один раз (находится только первая буква "а"), но затем сразу следует крах всей программы..

Сообщение отредактировано: redeezko -
 Оффлайн  Профиль  PM 
 К началу страницы 
+ Ответить 
сообщение
Сообщение #6


Гуру
*****

Группа: Пользователи
Сообщений: 1 013
Пол: Мужской
Ада: Разработчик
Embarcadero Delphi: Сторонник
Free Pascal: Разработчик

Репутация: -  627  +


Цитата
в Trie дереве подсчитать количество слов, в которых имеется буква "а"
По аналогии с методом Print:
function TTrieTree.CountAWords : Integer;

var
   Count : Integer;

   procedure ComposeString(T : TrieTree; s : string);
   var Ch : Tindex;
   begin
      if T^.Eow then if Pos('a', s) > 0 then Inc(Count);

      for Ch := Low (Tindex) to High (TIndex) do
         if T^.Ptrs[Ch] <> nil then
         begin
            ComposeString(T^.Ptrs[ch], s + ch);
         end;
   end;

begin
   Count := 0;
   if not Empty then
      ComposeString(TTree, '')
   else
      writeln('Tree is empty');
   CountAWords := Count;
end;
Можн, конечно, еще пошаманить, чтоб всю строку не собирать...
 Оффлайн  Профиль  PM 
 К началу страницы 
+ Ответить 
сообщение
Сообщение #7


Новичок
*

Группа: Пользователи
Сообщений: 22
Пол: Мужской

Репутация: -  0  +


Большое спасибо! smile.gif Так все получилось, хотя способ и правда не самый лучший.
 Оффлайн  Профиль  PM 
 К началу страницы 
+ Ответить 
сообщение
Сообщение #8


Гуру
*****

Группа: Пользователи
Сообщений: 1 013
Пол: Мужской
Ада: Разработчик
Embarcadero Delphi: Сторонник
Free Pascal: Разработчик

Репутация: -  627  +


Вот чуть лучше:
function TTrieTree.CountAWords : Integer;

var
   Count : Integer;

   procedure ComposeString(APresent: boolean; T : TrieTree);
   var Ch : Tindex;
   begin
      if T^.Eow then if APresent then Inc(Count);

      for Ch := Low (Tindex) to High (TIndex) do
         if T^.Ptrs[Ch] <> nil then
         begin
            ComposeString(APresent or (Ch = 'a'), T^.Ptrs[ch]);
         end;
   end;

begin
   Count := 0;
   if not Empty then
      ComposeString(false, TTree)
   else
      writeln('Tree is empty');
   CountAWords := Count;
end;
, от явного собирания строк избавились, от проверок Pos-ом тоже.
 Оффлайн  Профиль  PM 
 К началу страницы 
+ Ответить 
сообщение
Сообщение #9


Гость






Выложите архив самой программки пожалуйста.
 К началу страницы 
+ Ответить 

 Ответить  Открыть новую тему 
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0

 



- Текстовая версия 20.04.2025 22:23
500Gb HDD, 6Gb RAM, 2 Cores, 7 EUR в месяц — такие хостинги правда бывают
Связь с администрацией: bu_gen в домене octagram.name