一.字典树
用了两种方法做,首先想到得是构造两颗树,一颗前缀树,一颗后缀树,树节点是一个结构体,储存着经过这个节点得所有编号,因为是顺序向树中添加节点,最后就是最大的,可以通过遍历两颗树得到两份链表,最后通过双指针从后往前找,第一个相同的就是最大的下标。
最后结果超时了,加入了一部分记忆化搜索,每一次找完就把这对前缀和后缀加入到一个链表里,下一次先在链表中找,没有在去树中找,最后还是超时了。后面学了第二种哈希表法,发现这个记忆化搜索有些问题,可以使用哈希表,有机会可以在做一次,优化一下。
struct tree
{
vector<int> id;
int next[27];
tree() {
memset(next, 0, sizeof(next));
}
};
struct jiji
{
string st1;
string st2;
int a;
};
class WordFilter {
public:
vector<jiji> ji1;
tree front[100100];
int a;
tree last[100100];
int b;
WordFilter(vector<string>& words) {
//建一颗前缀树,一颗后缀树
//树的节点上保留这个前缀的所有结点的信息
//前后缀树各能得到一份id
//从后向前,双指针找出相同的最大的id
a = 0;
b = 0;
for (int i = 0; i < words.size(); i++)
{
int ptemp = 0;
for (int j = 0; j < words[i].length(); j++)
{
if (front[ptemp].next[words[i][j] - 'a'] == 0)
{
front[ptemp].next[words[i][j] - 'a'] = ++a;
ptemp = a;
front[ptemp].id.push_back(i);
}
else
{
ptemp = front[ptemp].next[words[i][j] - 'a'];
front[ptemp].id.push_back(i);
}
}
}
for (int i = 0; i < words.size(); i++)
{
int ptemp = 0;
for (int j = words[i].length() - 1; j >= 0; --j)
{
if (last[ptemp].next[words[i][j] - 'a'] == 0)
{
last[ptemp].next[words[i][j] - 'a'] = ++b;
ptemp = b;
last[ptemp].id.push_back(i);
}
else
{
ptemp = last[ptemp].next[words[i][j] - 'a'];
last[ptemp].id.push_back(i);
}
}
}
}
int f(string pref, string suff) {
for(int i = 0;i < ji1.size() ;i ++)
{
if(ji1[i].st1 == pref && ji1[i].st2 == suff)
{
return ji1[i].a;
}
}
int fr = 0;
int las = 0;
int ptemp = 0;
for (int i = suff.length() - 1; i >= 0; --i)//后缀树得到id
{
if (last[ptemp].next[suff[i] - 'a'] != 0)
{
ptemp = last[ptemp].next[suff[i] - 'a'];
if (i == 0)
{
//las = last[ptemp].id;
las = ptemp;
}
}
else
break;
}
ptemp = 0;
for (int i = 0; i < pref.length(); i++)//前缀树得到id
{
if (front[ptemp].next[pref[i] - 'a'] != 0)
{
ptemp = front[ptemp].next[pref[i] - 'a'];
if (i == pref.length() - 1)
{
//fr = front[ptemp].id;
fr = ptemp;
}
}
else
break;
}
int lef = (front[fr]).id.size() - 1;
int rig = (last[las]).id.size() - 1;
while (lef >= 0 && rig >= 0)
{
if (front[fr].id[lef] > last[las].id[rig])
{
lef--;
}
else if (front[fr].id[lef] < last[las].id[rig])
{
rig--;
}
else
{
jiji ko;
ko.st1 = pref;
ko.st2 = suff;
ko.a = front[fr].id[lef];
ji1.push_back(ko);
return front[fr].id[lef];
}
}
jiji ko;
ko.st1 = pref;
ko.st2 = suff;
ko.a = -1;
ji1.push_back(ko);
return -1;
}
};
/**
* Your WordFilter object will be instantiated and called as such:
* WordFilter* obj = new WordFilter(words);
* int param_1 = obj->f(pref,suff);
*/
二.哈希表
用特殊字符把一个单词的前后缀的所有组合连在一起,找的时候同样讲前后缀拼接在一起,进行查询
class WordFilter {
public:
unordered_map<string, int> mmap;
//通过哈希表储存一个单词的所有前后缀的可能,后面int对应最大下标
WordFilter(vector<string>& words) {
//特殊字符连接构件哈希表
auto ite = words.begin();
int ant = 0;
while (ite != words.end())
{
int m = (*ite).length();
for (int i = 1; i <= m; i++)
{
for (int j = m; j >= 0; j--)
{
string str = (*ite).substr(0, i) + "#" + (*ite).substr(m - j, j);
mmap[str] = ant;
}
}
ant++;
ite++;
}
}
int f(string pref, string suff) {
string str = pref + "#" + suff;
return mmap.count(str) ? mmap[str] : -1;
}
};