Главная страница


ru.algorithms

 
 - RU.ALGORITHMS ----------------------------------------------------------------
 From : Ihor Bobak                           2:5020/400     22 May 2001  11:37:58
 To : All
 Subject : Re: Поиск набора слов в тексте с помощью конечных автоматов
 -------------------------------------------------------------------------------- 
 
 > Hе факт, что у него был именно автомат. С той же производительностью
 > можно использовать дерево цифрового поиска "trie", описанное в
 > 3-м томе Кнута. В принципе, можно сказать, что TRIE от конечного
 > автомата отличается только тем, что в дереве есть терминальные
 > узлы - листься, тогда как в автомате из этих терминалюных
 > узлов стоят связи на ROOT - то есть КА можно рассматривать как
 > закольцованное TRIE.
 
 Так и есть: из терминальных узлов стоят связи на Root.
 
 > Hу если все же упереться в КА, есть 3 способа построить такую
 > байду:
 >
 > 1. По набору слов статически ручками прописать автомат и
 > интерпретатор дла него.
 
 Что вы имеете в виду под "по набору слов статически ручками"?
 Это как? Меня как раз и интересует алгоритм построения автомата
 по набору слов (а не по одному слову).
 
 > 2. Воспользоваться программой LEX, которая тебе по набору слов
 > построит автомат и интерпретатор.
 
 К сожалению, не знаю, о чем идет речь. Вы не могли бы конкретизировать,
 что это за программа?
 
 > 3. Динамически создавать TRIE в памяти, а потом закольцевать его.
 
 С этим все ясно: надо посмотреть в Кнута.
 
 - ---
 
 Вот эталонное (суддейское) решение, любезно предоставленное
 мне после окончания олимпиады:
 program Multi_Pattern_Matching;
 const
      InFile                     = 'B.DAT';
      DataFile                   = 'Count.Dat';
      OutFile                    = 'Count.Out';
      MaxSize                    = 20;
      MaxN                       = 200;
      BegChar                    = 'a';
      FinChar                    = 'z';
 type
     PNode                       = ^TNode;
     TNode                       = record
                                     Num : Integer;
                                     Fail, OutLink : PNode;
                                     Edge : array[BegChar..FinChar] of PNode;
                                   end;
     TTranWord                   = record
                                     S : string[MaxSize];
                                     L : Byte;
                                     P : PNode;
                                   end;
 var
    TranWord                     : array[1..MaxN] of TTranWord;
    InData                       : array[0..MaxN] of LongInt;
    F,FOut                            : Text;
    Root                         : PNode;
    N                            : LongInt;
 
 {~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 ~}
 procedure Init(var P : Pnode; Num : Integer; Fail : Pnode);
 var
    C                            : Char;
 begin
   New(P);
   P^.Num := Num;
   P^.Fail := Fail;
   P^.OutLink := nil;
   for C := BegChar to FinChar do P^.Edge[C] := nil;
 end;
 
 {~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 ~}
 procedure InPut;
 var
    K, I                         : Integer;
    Prev, CurFail                : PNode;
    C                            : Char;
 begin
 {reading}
   Readln(F,N);
   For i:=1 to N do
   begin
     ReadLn(F, TranWord[i].S);
     TranWord[i].L := Length( TranWord[i].S );
   end;
 
 {init for the root of the tree}
   Init(Root,0,nil);
 {making the first level}
   for I := 1 to N do with TranWord[I] do begin
     C := S[1];
     if Root^.Edge[C] = nil then Init(Root^.Edge[C],0,Root);
     P := Root^.Edge[C];
     if L = 1 then P^.Num := I;
   end;
 {making the other levels}
   for K := 2 to MaxSize do
     for I := 1 to N do with TranWord[I] do
       if K <= L then begin
         Prev := P;
         C := S[K];
         if Prev^.Edge[C] = nil then begin
           Init(Prev^.Edge[C],0,nil);
           P := Prev^.Edge[C];
           if L = K then P^.Num := I;
           CurFail := Prev^.Fail;
           while (CurFail <> Root) and
                 (CurFail^.Edge[C] = nil) do CurFail := CurFail^.Fail;
           if CurFail^.Edge[C] = nil then P^.Fail := Root
                                     else P^.Fail := CurFail^.Edge[C];
           if P^.Fail^.Num = 0 then P^.OutLink := P^.Fail^.OutLink
                               else P^.OutLink := P^.Fail;
         end else begin
           P := Prev^.Edge[C];
           if L = K then P^.Num := I;
         end;
       end;
 end;
 
 {~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 ~}
 procedure OutPut;
 var
    I                            : Integer;
 begin
   for I := 1 to N do
     WriteLn('The word ', TranWord[I].S, ' occurs ', InData[I], ' time(s).');
 end;
 
 {~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 ~}
 procedure ReadF(var C : Char);
 begin
   if Eoln(F) then ReadLn(F);
   if (Eof(F)) then
   begin
    OutPut;
    exit;
   end else Read(F, C);
   If C='$' then OutPut;
 end;
 
 {~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 ~}
 procedure CheckOccurrence(W : PNode);
 begin
   while (W <> Root) and (W <> nil) do begin
     Inc(InData[W^.Num]);
     W := W^.OutLink;
   end;
 end;
 
 {~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 ~}
 procedure Go;
 var
    W                            : PNode;
    C                            : Char;
 begin
   FillChar(InData, SizeOf(InData), 0);
   ReadF(C);
   W := Root;
   repeat
     while W^.Edge[C] <> nil do begin
       W := W^.Edge[C];
       CheckOccurrence(W);
       ReadF(C);
      if c='$' then exit;
     end;
     if W = Root then ReadF(C)
                 else W := W^.Fail;
     if c='$' then exit;
   until False;
 end;
 
 {~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 ~}
 var p : pointer;
     NumOfTest,CurTest : integer;
 begin
   Mark(p);
   Assign(F, InFile); ReSet(F);
   Readln(F,NumOfTest);
   For Curtest:=1 to NumOfTest do
   begin
    Writeln(FOut,'TEST ',CurTest);
    InPut;
    Go;
    Release(P);
   end;
   Close(F);
 end.
 
 {
 С уважением,
 игорь Бобак
 }
 --- ifmail v.2.15dev5
  * Origin: MTU-Intel ISP (2:5020/400)
 
 

Вернуться к списку тем, сортированных по: возрастание даты  уменьшение даты  тема  автор 

 Тема:    Автор:    Дата:  
 Поиск набора слов в тексте с помощью конечных автоматов   Ihor Bobak   21 May 2001 20:41:20 
 Re: Поиск набора слов в тексте с помощью конечных автоматов   Oleg I. Khovayko   21 May 2001 22:04:23 
 Re: оHХЯЙ МЮАHПЮ ЯКHБ Б РЕЙЯРЕ Я ОHЛHЫЭЧ ЙHМЕВМШУ ЮБРHЛЮРHБ   Borodin Anatoly   21 May 2001 23:27:10 
 Re: Поиск набора слов в тексте с помощью конечных автоматов   Ihor Bobak   22 May 2001 11:37:58 
 Re: Поиск набора слов в тексте с помощью конечных автоматов   Oleg I. Khovayko   22 May 2001 19:41:07 
 Re: оHХЯЙ МЮАHПЮ ЯКHБ Б РЕЙЯРЕ Я ОHЛHЫЭЧ ЙHМЕВМШУ ЮБРHЛЮРHБ   Borodin Anatoly   22 May 2001 20:19:48 
 Поиск набора слов в тексте с помощью конечных автоматов   Aleksey V. Vaneev   22 May 2001 19:48:44 
Архивное /ru.algorithms/910432f3e84d.html, оценка 2 из 5, голосов 10
Яндекс.Метрика
Valid HTML 4.01 Transitional