leetCode_Palindrome Pairs

题意:给定一系列单词,若某两个单词拼接起来是回文串,则把这两个单词下标组成的二元组成为“回文对”,找出所有的回文对。

方法:其实很简单,对于任意两个单词a,b,假设b的长度大于a。则a+b是回文串的条件是字符串b从最后一位到前面某一位反转字符串是a并且b串中该位置到第一位是回文串,若b+a是回文串的条件是字符串b从第一位开始到某一位反转的字符串是a并且b串中该位置到最后一位的串是回文串。所以对于每一个串,只要分情况判断即可。

有两个坑:

1、空串的情形。空串和任何回文字符串拼接都是回文串

2、若a是b的反转串,则第一种情况时b的下标是[b.length()-1,0],第二种情况的下标是[1,b.length()-1]。否则答案会输出两遍。

如何保存呢?用trie树和用set都可以,貌似用set效率高一点,还好写。我吭哧吭哧(keng chi)把trie树给写了,发现效率还没有set高,泪崩。。。我就贴一下我用trie树的代码吧。

struct node
{
    struct node *next[26];
    int level;
    int index;
    node(int q)
    {
        level=q;
        index=-1;
        int i;
        for(i=0;i<26;i++) next[i]=NULL;
    }
};
bool check(string s,int start,int end)
{
    if(end<=start) return true;
    string t=s.substr(start,end-start+1);
    int i;
    for(i=0;i<t.length()/2;i++) if(t[i]!=t[t.length()-1-i]) return false;
    return true;
}
vector<vector<int>> getPalindromePairs(vector<string>& words,int tag)
{
    vector<vector<int>> ans;
    vector<int> res;
    int i,j,k;
    struct node *tree=new node(-1),*temp;
    for(i=0;i<words.size();i++)
    {
        temp=tree;
        for(j=0;j<words[i].length();j++)
        {
            if(temp->next[words[i][j]-'a']==NULL) temp->next[words[i][j]-'a']=new node(j);
            temp=temp->next[words[i][j]-'a'];
        }
        temp->index=i;
    }
    for(i=0;i<words.size();i++)
    {
        temp=tree;
        for(j=words[i].length()-1;j>=tag+0;j--)
        {
            temp=temp->next[words[i][j]-'a'];
            if(temp==NULL) break;
            if(temp->index!=i&&temp->index!=-1&&check(words[i],0,j-1))
            {
                res.clear();
                res.push_back(temp->index);
                res.push_back(i);
                ans.push_back(res);
            }
        }
    }
    deleteTree(tree);
    return ans;
}
void deleteTree(struct node * tree)
{
    int i;
    for(i=0;i<26;i++) if(tree->next[i]!=NULL) deleteTree(tree->next[i]);
    delete tree;
    
}
vector<vector<int>> palindromePairs(vector<string>& words)
{
    vector<vector<int>> ans1;
    ans1=getPalindromePairs(words,0);
    vector<int> temp;
    
    int i,j,k,empty=-1;
    for(i=0;i<words.size();i++)
    {
        if(words[i].length()==0) empty=i;
        for(j=0;j<words[i].length()/2;j++) swap(words[i][j],words[i][words[i].length()-1-j]);
    }
    vector<vector<int>> ans2=getPalindromePairs(words,1);
    for(i=0;i<ans2.size();i++)
    {
        temp.clear();
        temp.push_back(ans2[i][1]);
        temp.push_back(ans2[i][0]);
        ans1.push_back(temp);
    }
    if(empty!=-1)
    {
        for(i=0;i<words.size();i++)
        {
            if(empty!=i&&check(words[i],0,words[i].length()-1))
            {
                temp.clear();
                temp.push_back(empty);
                temp.push_back(i);
                ans1.push_back(temp);
                temp.clear();
                temp.push_back(i);
                temp.push_back(empty);
                ans1.push_back(temp);
            }
        }
    }
    return ans1;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值