1.KMP查找算法
1.1 用途
给定一个主串,一个查找串,需要找到查找串在主串中第一次出现的位置(下标)。
1.2 方法
要求主串不回头(就是只想主串的指针不向后移动),查找串(匹配串)回头跳转。 这是一种以空间换时间的方法。
1.3 串的前缀与后缀
1.字符串的前缀是指字符串的任意首部,比如字符串“abbc”的前缀有 a ab abb ; 2.字符串的后缀是指字符串的任意尾部,比如字符串“abbc”的后缀有 c bc bbc ;
1.4 KMP算法就是找两个串中的最大相等的前缀和后缀。
1.5 KMP算法的核心就是计算 Next 数组。
1.6 求 “aababaaabbcabbaa” 的 Next 数组
1.即使用一个和字符串等长的数组来存储当前字符串前缀与后缀最大的相等长度。 2.Next 数组为 [0101012230010012] ;
1.7 使用 Next 数组进行匹配
1.8 KMP算法步骤
int * GetNext ( char * match)
{
int * p_next = NULL ;
p_next = ( int * ) malloc ( sizeof ( int ) * strlen ( match) ) ;
p_next[ 0 ] = 0 ;
int i = 1 ;
int j = i - 1 ;
while ( i < strlen ( match) )
{
if ( match[ i] == match[ p_next[ j] ] )
{
p_next[ i] = p_next[ j] + 1 ;
i++ ;
j = i - 1 ;
}
else if ( p_next[ j] == 0 )
{
p_next[ i] = 0 ;
i++ ;
j = i - 1 ;
}
else
{
j = p_next[ j] - 1 ;
}
}
return p_next;
}
int KMP ( char * str, char * match)
{
if ( str == NULL || match == NULL ) return - 1 ;
int * p_next = NULL ;
p_next = GetNext ( match) ;
int i = 0 ;
int j = 0 ;
while ( i < strlen ( str) && j < strlen ( match) )
{
if ( str[ i] == match[ j] )
{
i++ ;
j++ ;
}
else
{
if ( j == 0 )
{
i++ ;
}
else
{
j = p_next[ j- 1 ] ;
}
}
}
if ( j == strlen ( match) )
{
return i - j;
}
else
{
return - 1 ;
}
}
2.Sunday算法
2.1 使用一个256维的数组来存储从右到左match的字母第一次出现的位置。
2.2 实现算法
int Sunday ( char * str, char * match)
{
if ( str == NULL || match == NULL ) return - 1 ;
int * p_next = NULL ;
p_next = ( int * ) malloc ( sizeof ( int ) * 256 ) ;
memset ( p_next, - 1 , sizeof ( int ) * 256 ) ;
int i;
for ( i= 0 ; i< strlen ( match) ; i++ )
{
p_next[ match[ i] ] = i;
}
int j;
int k;
i = 0 ;
j = 0 ;
while ( i < strlen ( str) && j < strlen ( match) )
{
k = i;
while ( str[ i] == match[ j] && i < strlen ( str) && j < strlen ( match) )
{
i++ ;
j++ ;
}
if ( j == strlen ( match) )
{
return i - j;
}
if ( k+ strlen ( match) < strlen ( str) )
{
k = k + strlen ( match) - p_next[ str[ k+ strlen ( match) ] ] ;
i = k;
j = 0 ;
}
else
{
return - 1 ;
}
}
}
3.字典树
3.1 功能
3.2 查找树没有空树的概念
3.3 每个节点不是字母,而是代表字母
3.4 实现
typedef struct trie
{
int n_count;
char * str;
struct trie* p_character[ 26 ] ;
} TrieTree;
TrieTree* GetNode ( )
{
TrieTree* p_node = NULL ;
p_node = ( TrieTree* ) malloc ( sizeof ( TrieTree) ) ;
memset ( p_node, 0 , sizeof ( TrieTree) ) ;
return p_node;
}
void AddWord ( TrieTree* p_tree, char * str)
{
int i = 0 ;
TrieTree* p_temp = NULL ;
while ( i < strlen ( str) )
{
if ( p_tree-> p_character[ str[ i] - 97 ] == NULL )
{
p_tree-> p_character[ str[ i] - 97 ] = GetNode ( ) ;
}
p_tree = p_tree-> p_character[ str[ i] - 97 ] ;
i++ ;
}
p_tree-> str = str;
p_tree-> n_count++ ;
}
TrieTree* CreateTrie ( char * str[ ] , int len)
{
if ( str == NULL || len <= 0 ) return NULL ;
TrieTree* p_tree = NULL ;
p_tree = GetNode ( ) ;
int i;
for ( i= 0 ; i< len; i++ )
{
AddWord ( p_tree, str[ i] ) ;
}
return p_tree;
}
void Search ( TrieTree* p_tree, char * str)
{
if ( p_tree == NULL || str == NULL ) return ;
int i = 0 ;
while ( i < strlen ( str) )
{
if ( p_tree-> p_character[ str[ i] - 97 ] == NULL )
{
printf ( "TAT failed.\n" ) ;
return ;
}
p_tree = p_tree-> p_character[ str[ i] - 97 ] ;
i++ ;
}
if ( p_tree-> n_count != 0 )
{
printf ( "%s\n" , p_tree-> str) ;
return ;
}
else
{
printf ( "QAQ failed.\n" ) ;
return ;
}
}
void Traversal ( TrieTree* p_tree)
{
if ( p_tree == NULL ) return ;
if ( p_tree-> n_count != 0 )
printf ( "%s\n" , p_tree-> str) ;
int i;
for ( i= 0 ; i< 26 ; i++ )
Traversal ( p_tree-> p_character[ i] ) ;
}