Зачем нужен блок else в методе "push_links" следующего кода?

Этот код для алгоритма Aho-Corasick, который я отсюда рецензировал

Я понял этот код до блока if метода push_links, но я не получил использование или требование для остальной части того же метода. Более конкретно, первый метод используется для построения дерева. Оставшаяся работа выполняется вторым методом, т.е. связывает узел с их самым длинным надлежащим суффиксом, который также является префиксом некоторого шаблона. Это выполняется блоком If, тогда зачем нужна другая часть.

Пожалуйста, помогите мне в этом.

const int MAXN = 404, MOD = 1e9 + 7, sigma = 26;

int term[MAXN], len[MAXN], to[MAXN][sigma], link[MAXN], sz = 1;    

  // this method is for constructing trie

void add_str(string s)    
{ 

  // here cur denotes current node   

  int cur = 0;    

  // this for loop adds string to trie character by character

  for(auto c: s)        
    {     
      if(!to[cur][c - 'a'])  
        {   

  //here two nodes or characters are linked using transition                                       
  //array "to"

         to[cur][c - 'a'] = sz++;  
         len[to[cur][c - 'a']] = len[cur] + 1;     

         }

  // for updating the current node  

       cur = to[cur][c - 'a'];  
    }

  //for marking the leaf nodes or terminals

   term[cur] = cur;   
}   


void push_links()  
{
 //here queue is used for breadth first search of the trie  
 int que[sz];  
 int st = 0, fi = 1;  

 //very first node is enqueued 
 que[0] = 0;   

 while(st < fi)  
   { 

 // here nodes in the queue are dequeued  
    int V = que[st++];  

 // link[] array contains the suffix links.
    int U = link[V];


    if(!term[V]) term[V] = term[U];   

  // here links for the other nodes are find out using assumption that the  
  // link for the parent node is defined    

   for(int c = 0; c < sigma; c++)   

   // this if condition ensures that transition is possible to the next node 
   // for input 'c' 

        if(to[V][c])    
        {   

   // for the possible transitions link to the reached node is assigned over 
   // here which is nothing but transition on input 'c' from the link of the 
   // current node

            link[to[V][c]] = V ? to[U][c] : 0;  
            que[fi++] = to[V][c];  
        }  
        else 
        {  
            to[V][c] = to[U][c];  
        }  
   }  
}

2 ответа

ИМО тебе не нужно другое условие. Если нет детей, то это либо ссылка, либо ничего.

Есть несколько вариантов алгоритма Aho-Corasick. Базовый алгоритм предполагает, что если ребро от текущего узла (cur) над символом (c) отсутствует, то вы переходите по суффиксным ссылкам к первому узлу, который имеет ребро над c (вы делаете движение через это ребро). Но ваш путь по суффиксным ссылкам тот же (из того же cur и c), потому что вы не меняете автомат при поиске. Таким образом, вы можете кэшировать его (сохранить результат

// start from node 
while (parent of node doesn't have an edge over c) {
  node = parent
}
// set trie position
node = to[node][c]
// go to next character

в [узел] [с]. Так что в следующий раз вы не будете делать это снова. И это превращает автомат из недетерминированного в детерминированный конечный автомат (вы не должны использовать массив ссылок после нажатия, вы можете использовать только для массива).

Есть некоторые проблемы с этой реализацией. Во-первых, вы можете получить индекс найденной строки (вы не сохраняете его). Кроме того, массив len нигде не используется.

За

означает, что этот алгоритм просто проверяет наличие символа в текущей ссылке на узел, используя "link[to[V][c]] = V? to[U][c]: 0;". не должно ли это проверить в родителях ссылку тоже?

Да, все в порядке, потому что если [U] [c] равно 0, то нет никаких ребер через c из всей цепочки U-> суффикс_парент-> суффикс родительского суффикса_парента... -> root = 0. Поэтому вы должны установить до [V] [с] до нуля.

Другие вопросы по тегам