题目:
一个字符串类型的数组arr1,另一个字符串类型的数组arr2。arr2中有哪些字符,是arr1中 出现的?请打印。arr2中有哪些字符,是作为arr1中某个字符串前缀出现的?请打印。请打印 arr2中出现次数最大的前缀。
分析:对于这种题目,就可以用到前缀树来解。如果arr1 = {a, b, c}, arr2 = {a, b , c , d, e},那么这两个字符串的前缀树如图。
前缀树的实现:
class TireNode{
public:
int path;
int end;
//这里认为字符串中只出现26个小写字母,如果出现的字符类型种类较多,可以考虑使用hashset。
TireNode* nexts[26] = {NULL};
TireNode(){
this->path = 0;
this->end = 0;
}
ostream& operator << (ostream& output) //定义运算符“<<”重载函数
{
output << "path:" << this->path << " end:" << this->end << endl;
return output;
}
};
class TireTree{
public:
TireNode* root;
TireTree(){
this->root = new TireNode();
}
void insert(string str){
if(str.empty()){
return;
}
this->root->path++;
TireNode* temp = root;
//cout << "root:" << root->path << " " << root->end << endl;
int index = 0;
for(int i = 0; i < str.length(); i++){
index = str[i] - 'a';
if(temp->nexts[index] == NULL)
temp->nexts[index] = new TireNode();
temp->nexts[index]->path++;
//cout << char(i + 'a') << " :" << root->nexts[index]->path << " " << root->nexts[index]->end << endl;
temp = temp->nexts[index];
}
temp->end++;
//cout << " :" << root->path << " " << root->end << endl;
}
void deleteStr(string str){
if(str.empty()){
return;
}
this->root->path --;
TireNode* temp = root,*p = root;
int index = 0;
for(int i = 0; i < str.length(); i++){
index = str[i] - 'a';
if(temp->nexts[index] != NULL){
p = temp->nexts[index];
temp = temp->nexts[index];
p->path--;
if(p->path == 0)
delete p;
}
}
if(temp != NULL)
temp->end--;
}
int search(string& str){
if(str.empty()){
return 0;
}
TireNode* temp = root,*p = root;
int index = 0;
for(int i = 0; i < str.length(); i++){
index = str[i] - 'a';
if(temp->nexts[index] == NULL){
return 0;
}
temp = temp->nexts[index];
}
return temp->end;
}
int prefixNumber(string str){
if(str.empty()){
return 0;
}
TireNode* temp = root,*p = root;
int index = 0;
for(int i = 0; i < str.length(); i++){
index = str[i] - 'a';
if(temp->nexts[index] == NULL){
return 0;
}
temp = temp->nexts[index];
}
return temp->path;
}
//深度遍历
void printfTireTree(int i,TireNode* root){
if(root == NULL){
return;
}
//TireNode* temp = root;
if(i < 0)
cout << "root: ";
else
cout << (char)(i + 'a') << ": ";
cout << root->path << " " << root->end << endl;
for(int i = 0; i < 26; i++){
printfTireTree(i,root->nexts[i]);
}
}
};
int main()
{
TireTree tree;
string str = "abc";
string str_1 = "abcde";
tree.insert(str);
tree.insert(str_1);
tree.printfTireTree(-1,tree.root);
//tree.deleteStr(str);
//tree.printfTireTree(-1,tree.root);
//cout << tree.search(str) << endl;
cout << tree.prefixNumber(str) << endl;
return 0;
}
前缀树应用:
字符串的检索;
字符串的排序,由上面的实现也可以看出,遍历时会按照abcd的字母顺序进行,减少了比较时间;
显示前缀;
匹配前缀显示后缀;