Помощь - Поиск - Пользователи - Календарь
Полная версия: подсчет слов в Trie дереве
Форум «Всё о Паскале» > Pascal, Object Pascal > Задачи
redeezko
Добрый день. Помогите пожалуйста с задачей: в 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.
Гость
Примерно так:

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;
...

redeezko
Спасибо большое за ответ =). Но непонятно LastLetter - это что за параметр? Что им будет в программе, при вызове
данной процедуры?
-TarasBer-
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.
redeezko
Что то не получается...
Вставил в свой код данную процедуру вот таким образом:
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, то она выполняется один раз (находится только первая буква "а"), но затем сразу следует крах всей программы..
IUnknown
Цитата
в 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;
Можн, конечно, еще пошаманить, чтоб всю строку не собирать...
redeezko
Большое спасибо! smile.gif Так все получилось, хотя способ и правда не самый лучший.
IUnknown
Вот чуть лучше:
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-ом тоже.
-Михаил-
Выложите архив самой программки пожалуйста.
Это текстовая версия — только основной контент. Для просмотра полной версии этой страницы, пожалуйста, нажмите сюда.