LC.336. 回文对(前缀字典树)
思路:前缀字典树。
考虑回文串对的组成:
若 ,则 是 的翻转。
,则 由 的翻转+回文串组成。
,则 由 的回文+翻转组成。
因此可以枚举每个子串的前后缀,查找剩余部分的翻转是否存在即可。
时间复杂度:
class Solution {
public:
struct node{
int ch[26],id;
node(){id=-1,memset(ch,0,sizeof ch);}
};
vector<node>tr;
void ins(string &s,int num){
int x=0,l=s.size();
for(int i=0;i<l;i++){
int c=s[i]-'a';
if(!tr[x].ch[c]) tr.emplace_back(),tr[x].ch[c]=tr.size()-1;
x=tr[x].ch[c];
}
tr[x].id=num;
}
bool jg(string &s,int l,int r){
int len=r-l+1;if(len<0) return false;
for(int i=0;i<len>>1;i++)
if(s[l+i]!=s[r-i]) return false;
return true;
}
int Find(string &s,int l,int r){
int x=0;
for(int i=r;i>=l;i--){
int c=s[i]-'a';
if(!tr[x].ch[c]) return -1;
x=tr[x].ch[c];
}
return tr[x].id;
}
vector<vector<int>> palindromePairs(vector<string>& w) {
tr.emplace_back();
int n=w.size();
for(int i=0;i<n;i++) ins(w[i],i);
vector<vector<int> >ans;
for(int i=0;i<n;i++){
int m=w[i].size();
for(int j=0;j<=m;j++){
if(jg(w[i],j,m-1)){
int id=Find(w[i],0,j-1);
if(~id&&id!=i) ans.push_back({i,id});
}
if(j&&jg(w[i],0,j-1)){
int id=Find(w[i],j,m-1);
if(~id&&id!=i) ans.push_back({id,i});
}
}
}
return ans;
}
};