具体思路:
又一个见到的升级版字典树问题;
难点不在于字典树,而在于前缀后缀判断;
如果建两棵树必定会超时;
这里有一个前后缀一起判断的方法;
对于字符串"abc";
可以构造"abc#abc";
之后构造:
abc#abc
bc#abc
c#abc
#abc
查询后缀前缀必定是上述四个的部分子串;
同时建树的时候设定index进行覆盖,这样可以保证索引最大的相同树结构可以覆盖之前的索引记录;
并且一定要记住,要逐层覆盖索引,因为前缀后缀拼合可能只是子序列,并非完整路径;
具体代码:
struct node{
node(){
children.resize(26,nullptr);
isend=false;
str="";
}
void insert(string& s){
node* root=this;
for(auto& ch:s){
int index=ch-'a';
if(root->children[index]==nullptr){
root->children[index]=new node();
}
root=root->children[index];
}
root->isend=true;
root->str=s;
}
vector<string> nodefind(string& str){
vector<string>ret;
node* root=this;
for(auto& ch:str){
int index=ch-'a';
if(root->children[index]==nullptr){
return ret;
}
root=root->children[index];
}
deep_find(root, ret);
return ret;
}
void deep_find(node* root,vector<string>& ret){
if(!root)
return;
if(root->isend){
ret.push_back(root->str);
}
for(auto& p:root->children){
deep_find(p, ret);
}
}
vector<node*> children;
bool isend;
string str;
};
class WordFilter {
public:
WordFilter(vector<string>& words) {
frontroot=new node();
forwardroot=new node();
int cnt=0;
for(auto& str:words){
frontroot->insert(str);
fump[str]=cnt;
reverse(str.begin(), str.end());
forwardroot->insert(str);
bump[str]=cnt;
cnt++;
}
}
int f(string prefix, string suffix) {
reverse(suffix.begin(),suffix.end());
vector<string>pre=frontroot->nodefind(prefix);
vector<string>suf=forwardroot->nodefind(suffix);
map<int,int>mp;
for(auto& str:pre){
int index=fump[str];
mp[index]++;
}
for(auto& str:suf){
int index=bump[str];
mp[index]++;
}
int maxn=-1;
for(auto it=mp.begin();it!=mp.end();it++){
if(it->second==2){
maxn=it->first;
}
}
return maxn;
}
private:
unordered_map<string,int>fump;
unordered_map<string,int>bump;
node* frontroot;
node* forwardroot;
};
/**
* Your WordFilter object will be instantiated and called as such:
* WordFilter* obj = new WordFilter(words);
* int param_1 = obj->f(prefix,suffix);
*/