字面意思,保存字符串前缀的树型结构。 根到任意节点的路径代表一个前缀,每个结点一个编号,根的编号为0。 Trie如上图,用二维数组ch[][]建树(类似邻接矩阵),ch[u][c]表示结点u通过编号为c的字母所到达的结点(u编号为c的子节点),同时为方便维护每个结点u对应权值val[u],如可以用来区分单词几点与非单词结点。 UVA1401 Remember the Word Trie+Dp
# include <iostream>
# include <cstdio>
# include <cstring>
using namespace std;
const int max_node = 400005 , sigma_size = 30 , Mod = 20071027 ;
char str[ 300005 ] , str0[ 105 ] ;
int n, d[ 300005 ] , num;
class Trie {
public :
Trie ( )
{
memset ( ch[ 0 ] , 0 , sizeof ( ch[ 0 ] ) ) ;
sz= 1 ;
}
void init ( ) { memset ( ch[ 0 ] , 0 , sizeof ( ch[ 0 ] ) ) ; sz= 1 ; }
int ids ( char c) { return c- 'a' ; }
void insert ( char * s, bool v)
{
int u= 0 , len= strlen ( s) ;
for ( int i= 0 ; i< len; i++ )
{
int c = ids ( s[ i] ) ;
if ( ! ch[ u] [ c] )
{
memset ( ch[ sz] , 0 , sizeof ( ch[ sz] ) ) ;
ch[ u] [ c] = sz++ ;
val[ sz] = 0 ;
}
u= ch[ u] [ c] ;
}
val[ u] = v;
}
int query ( char * s, int fir)
{
int u = 0 , len= strlen ( s) , ans = 0 ;
for ( int i= 0 ; i< len; i++ )
{
int c = ids ( s[ i] ) ;
if ( ! ch[ u] [ c] ) break ;
u = ch[ u] [ c] ;
if ( val[ u] )
ans= ( ans+ d[ fir+ i+ 1 ] ) % Mod;
}
return ans;
}
private :
int ch[ max_node] [ sigma_size] ;
int sz;
bool val[ max_node] ;
} ;
Trie t;
void init ( int len)
{
d[ len] = 1 ;
t. init ( ) ;
}
int main ( )
{
while ( scanf ( "%s" , str) != EOF )
{
num++ ;
scanf ( "%d" , & n) ;
init ( strlen ( str) ) ;
for ( int i= 1 ; i<= n; i++ )
{
scanf ( "%s" , str0) ;
t. insert ( str0, 1 ) ;
}
int len = strlen ( str) ;
for ( int i= len- 1 ; i>= 0 ; i-- )
d[ i] = t. query ( & str[ i] , i) ;
printf ( "Case %d: %d\n" , num, d[ 0 ] ) ;
}
return 0 ;
}