link

class Solution {
public:
struct TrieNode{
TrieNode* children[26];
int id;
TrieNode(){
id=-1;
for(int i=0;i<26;i++) children[i]=nullptr;
}
};
TrieNode* root;
vector<vector<int>> palindromePairs(vector<string>& words) {
root=new TrieNode();
for(int i=0;i<words.size();i++){
build(words[i],i);
}
vector<vector<int>> res;
for(int i=0;i<words.size();i++){
if(words[i]=="") continue;
auto rec1=findmaxlen(words[i]);
string rs=words[i];
reverse(rs.begin(),rs.end());
auto rec2=findmaxlen(rs);
int len=words[i].size();
if(rec1[len-1]==len){
if(root->id!=-1){
res.push_back({i,root->id});
res.push_back({root->id,i});
}
}
int id=find(words[i],0,words[i].size()-1);
if(id!=-1 && id>i){
res.push_back({i,id});
res.push_back({id,i});
}
for(int j=0;j<len-1;j++){
if(rec2[j]==j+1){
int id=find(words[i],0,len-j-2);
if(id!=-1) res.push_back({i,id});
}
}
for(int j=0;j<len-1;j++){
if(rec1[j]==j+1){
int id=find(words[i],j+1,len-1);
if(id!=-1) res.push_back({id,i});
}
}
}
return res;
}
int find(string& s, int left, int right){
TrieNode* cur=root;
for(int i=right;i>=left;i--){
char c=s[i];
if(cur->children[c-'a']==nullptr) return -1;
cur=cur->children[c-'a'];
}
return cur->id;
}
void build(string& s, int idx){
TrieNode* cur=root;
for(char c:s){
if(cur->children[c-'a']==nullptr){
cur->children[c-'a']=new TrieNode();
}
cur=cur->children[c-'a'];
}
cur->id=idx;
}
vector<int> findmaxlen(string& s){
int n=s.size();
vector<int> res(n);
string tmp="#";
for(char c:s){
tmp.push_back(c);
tmp.push_back('#');
}
int m=tmp.size();
vector<int> T(m);
int mid=0;
int rightB=0;
for(int i=1;i<m;i++){
if(i<rightB){
T[i]=min(rightB-i,T[2*mid-i]);
}
while(i-T[i]>=0 && i+T[i]<m && tmp[i-T[i]]==tmp[i+T[i]]){
T[i]++;
}
T[i]--;
res[(i+T[i]-1)/2]=max(res[(i+T[i]-1)/2],T[i]);
if(i+T[i]>rightB){
mid=i;
rightB=i+T[i];
}
}
return res;
}
};