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

 





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