word_db.cc
上传用户:psq1974
上传日期:2007-01-06
资源大小:1195k
文件大小:8k
源码类别:

mpeg/mp3

开发平台:

C/C++

  1. /* Copyright (C) 1998, 1999 State University of New York at Stony Brook
  2.    Author: Andrew V. Shuvalov ( andrew@ecsl.cs.sunysb.edu )
  3.    Software license is located in file "COPYING"
  4. */
  5. #include <stdio.h>
  6. #include <string>
  7. #include <queue>
  8. #include <algorithm>
  9. #include "word_db.h"
  10. const string WordDb::spaces(" tn.;,:!@-=/\(){}" );
  11. WordTreeNode *WordTreeNode::get_child( int ch )
  12. {
  13.   if( childrens.find( ch ) == childrens.end() )  // create new
  14.     {
  15.       WordTreeNode *node = new WordTreeNode();
  16.       childrens[ ch ] = node;
  17.       return node;
  18.     }
  19.   return childrens[ ch ];
  20. }
  21. void WordTreeNode::register_word( int movieId, int strIdx, int posInLine )
  22. {
  23.   WordOccurence wo( movieId, strIdx, posInLine );
  24.   WordOccurences.push_back( wo );
  25. }
  26. // -----------------------------------------------------------------------
  27. const TextOfMovieT *WordDb::get_movie_text( int id )
  28. {
  29.   if( allTextsMap.find( id ) == allTextsMap.end() )
  30.     return 0;
  31.   return allTextsMap[ id ];
  32. }
  33. const StringOfText *WordDb::get_string_of_text( int movieId, 
  34. int linenum ) const
  35. {
  36.   if( allTextsMap.find( movieId ) == allTextsMap.end() )
  37.     return 0;
  38.   
  39.   AllTextsMapT::const_iterator it = allTextsMap.find( movieId );
  40.   const TextOfMovieT *tom = (*it).second;
  41.   if( tom->size() <= linenum || linenum < 0 )
  42.     return 0;
  43.   return &(*tom)[ linenum ];
  44. }
  45. void WordDb::add_new_movie_text( int id, TextOfMovieT *tom )
  46. {
  47.   allTextsMap[id] = tom;
  48.   // and put text into search tree
  49.   for( int i = 0; i < tom->size(); i++ )
  50.     insert_new_string_in_search_tree( (*tom)[i].get_text(), id, i );
  51. }
  52. void WordDb::insert_new_string_in_search_tree( const string &str, 
  53.        int movieId, int strIdx )
  54. {
  55.   string::size_type pos = 0;
  56.   str.c_str();
  57.   int posInLine = 0;
  58.   while( pos != str.npos )
  59.     {
  60.       pos = str.find_first_not_of( spaces, pos );
  61.       if( pos == str.npos )
  62. break;
  63.       int pos_end = str.find_first_of( spaces, pos );
  64.       string word = str.substr( pos, pos_end != str.npos? pos_end - pos:
  65. str.npos );
  66.       word.c_str();
  67.       insert_new_word_in_search_tree( word, movieId, strIdx, posInLine );
  68.       posInLine ++;
  69.       pos = pos_end;
  70.     }
  71. }
  72. void WordDb::insert_new_word_in_search_tree( const string &w, int movieId, 
  73.      int strIdx, int posInLine )
  74. {
  75.   if( !w.length() )
  76.     return;
  77.   w.c_str();
  78.   // remember, we need case-insensative 
  79.   WordTreeNode *node = &parentNode;
  80.   for( int pos = 0; pos < w.length(); pos++ )
  81.     {
  82.       int ch = tolower( w[ pos ] );
  83.       node = node->get_child( ch );
  84.       // this is the last char or not?
  85.       if( pos == w.length() - 1 )
  86. node->register_word( movieId, strIdx, posInLine );
  87.     }
  88. }
  89. const WordOccurencesT &WordDb::find_word( const string &w ) const
  90. {
  91.   static WordOccurencesT nothing;
  92.   if( !w.length() )
  93.     return nothing;
  94.   w.c_str();
  95.   // remember, we need case-insensative 
  96.   const WordTreeNode *node = &parentNode;
  97.   for( int pos = 0; pos < w.length(); pos++ )
  98.     {
  99.       int ch = tolower( w[ pos ] );
  100.       node = node->get_child( ch );
  101.       // this is the last char or not?
  102.       if( pos == w.length() - 1 )
  103. return node->get_word_occurences();
  104.     }
  105.   // nothing
  106.   return nothing;
  107. }
  108. void WordDb::find_similar_words( const string &word, GList *&similar ) const
  109. {
  110.   if( !word.length() )
  111.     return;
  112.   // where to store strings to avoid memory leaks
  113.   static vector< string * > strings;
  114.   for( int i = 0; i < strings.size(); i++ )
  115.     delete strings[i];
  116.   strings.clear();
  117.   word.c_str();
  118.   // remember, we need case-insensative 
  119.   const WordTreeNode *node = &parentNode;
  120.   for( int pos = 0; pos < word.length(); pos++ )
  121.     {
  122.       int ch = tolower( word[ pos ] );
  123.       node = node->get_child( ch );
  124.       // this is the last char or not?
  125.       if( pos == word.length() - 1 )
  126. {
  127.   for( WordTreeNode::childrensT::const_iterator it = 
  128.  node->get_all_childrens().begin(); 
  129.        it != node->get_all_childrens().end(); it++ )
  130.     {
  131.       if( (*it).second->get_word_occurences().size() > 0 )
  132. {
  133.   string *nw = new string( word + (char)(*it).first );
  134.   strings.push_back( nw );
  135.   similar = g_list_append( similar, (void*)nw->c_str() );
  136. }
  137.     }
  138.   break;
  139. }
  140.     }
  141. }
  142. void  WordDb::find_hint_words( const string &word, GList *&similar ) const
  143. {
  144.   if( !word.length() )
  145.     return;
  146.   // where to store strings to avoid memory leaks
  147.   static vector< string * > strings;
  148.   for( int i = 0; i < strings.size(); i++ )
  149.     delete strings[i];
  150.   strings.clear();
  151.   word.c_str();
  152.   // remember, we need case-insensative 
  153.   const WordTreeNode *node = &parentNode;
  154.   for( int pos = 0; pos < word.length(); pos++ )
  155.     {
  156.       int ch = tolower( word[ pos ] );
  157.       node = node->get_child( ch );
  158.       // this is the last char or not?
  159.       if( pos == word.length() - 1 )
  160. {
  161.   const WordOccurencesT &wo = node->get_word_occurences();
  162.   for( int i = 0; i < wo.size(); i++ )
  163.     for( int j = -1; j <= 1; j++ )
  164.       {
  165. const StringOfText *sot = 
  166.   get_string_of_text(wo[i].get_movie_id(),wo[i].get_text_line()+j);
  167. if( sot )
  168.   {
  169.     const string &text = sot->get_text();
  170.     string::size_type pos = 0;
  171.     while( pos != text.npos )
  172.       {
  173. pos = text.find_first_not_of( spaces, pos );
  174. if( pos == text.npos )
  175.   break;
  176. string::size_type pos_end = text.find_first_of(spaces,pos);
  177. string *hword = new string
  178.   ( text.substr( pos, pos_end != text.npos? 
  179.  pos_end - pos: text.npos ) );
  180. hword->c_str();
  181. const WordOccurencesT &hwo = find_word( *hword );
  182. if( hwo.size() <= wo.size() && *hword != word )
  183.   {
  184.     strings.push_back( hword );
  185.     similar = g_list_append(similar,(void*)hword->c_str());
  186.   }
  187. pos = pos_end;
  188.       }
  189.   }
  190.       }
  191. }
  192.     }
  193. }
  194. WordOccurencesT WordDb::merge_and( const WordOccurencesT &left, 
  195.    const WordOccurencesT &right ) const
  196. {
  197.   // put both data in the heap and merge head by head
  198.   priority_queue< WordOccurence > lheap( left.begin(), left.end() );
  199.   priority_queue< WordOccurence > rheap( right.begin(), right.end() );
  200.   WordOccurencesT result;
  201.   while( lheap.size() && rheap.size() )
  202.     {
  203.       WordOccurence l = lheap.top();
  204.       lheap.pop();
  205.       WordOccurence r = rheap.top();
  206.       rheap.pop();
  207.       if( l.is_near( r ))
  208. {
  209.   result.push_back( l );
  210.   continue;
  211. }
  212.       // not near
  213.       if( l > r )
  214. {
  215.   while( lheap.size() && l > r )
  216.     {
  217.       l = lheap.top();
  218.       lheap.pop();
  219.       if( l.is_near( r ) )
  220. {
  221.   result.push_back( l );
  222.   break;
  223. }
  224.     }
  225.   continue;
  226. }
  227.       if( r > l )
  228. {
  229.   while( rheap.size() && r > l )
  230.     {
  231.       r = rheap.top();
  232.       rheap.pop();
  233.       if( l.is_near( r ) )
  234. {
  235.   result.push_back( l );
  236.   break;
  237. }
  238.     }
  239.   continue;
  240. }
  241.     }      
  242.   return result;
  243. }
  244. WordOccurencesT WordDb::merge_and_not( const WordOccurencesT &left, 
  245.        const WordOccurencesT &right ) const
  246. {
  247.   // put both data in the heap and merge head by head
  248.   priority_queue< WordOccurence > lheap( left.begin(), left.end() );
  249.   priority_queue< WordOccurence > rheap( right.begin(), right.end() );
  250.   WordOccurencesT result;
  251.   while( lheap.size() && rheap.size() )
  252.     {
  253.       WordOccurence l = lheap.top();
  254.       lheap.pop();
  255.       WordOccurence r = rheap.top();
  256.       rheap.pop();
  257.       if( l.is_near( r ))
  258. {
  259.   // trash both
  260.   continue;
  261. }
  262.       // not near
  263.       if( l > r )
  264. {
  265.   while( lheap.size() && l > r )
  266.     {
  267.       // just what we need 
  268.       result.push_back( l );
  269.       l = lheap.top();
  270.       lheap.pop();
  271.       if( l.is_near( r ) )
  272. {
  273.   // trash both
  274.   break;
  275. }
  276.     }
  277.   continue;
  278. }
  279.       if( r > l )
  280. {
  281.   while( rheap.size() && r > l )
  282.     {
  283.       // just what we need 
  284.       result.push_back( r );
  285.       
  286.       r = rheap.top();
  287.       rheap.pop();
  288.       if( l.is_near( r ) )
  289. {
  290.   // trash both
  291.   break;
  292. }
  293.     }
  294.   continue;
  295. }
  296.     }      
  297.   return result;
  298. }
  299. WordOccurencesT WordDb::merge_or( const WordOccurencesT &left, 
  300.   const WordOccurencesT &right ) const
  301. {
  302.   // true merge
  303.   WordOccurencesT result;
  304.   result.resize( left.size() + right.size() );
  305.   merge( left.begin(), left.end(), right.begin(), right.end(), 
  306.  result.begin() );
  307.   return result;
  308. }