• LeetCode 回文子串


    5. 最长回文子串

    题目描述:

    解法一(暴力求解):

    class Solution {
    public:
        string longestPalindrome(string s) {
            int n=s.size();
            string res;
            for(int i=0;i<n;i++){
                for(int j=i;j<n;j++){
                    string temp=s.substr(i,j-i+1),rev=temp;
                    reverse(rev.begin(),rev.end());
                    if(temp==rev&&temp.size()>res.size())
                        res=temp;
                }
            }
            return res;
        }
    };
    
    class Solution {
    public:
        string longestPalindrome(string s) {
            string res;
            string str;
            for(int i=0;i<s.size();i++){
                for(int j=i;j<s.size();j++){
                    str+=s[j];
                    string rev=str;
                    reverse(rev.begin(),rev.end());
                    if(str==rev&&str.size()>res.size())
                        res=str;
                }
                str="";
            }
            return res;
        }
    };
    
    
    class Solution {
    public:
        bool isPalindrome(string s){
            int len=s.size();
            for(int i=0;i<len/2;i++){
                if(s[i]!=s[len-i-1])
                    return false;
            }
            return true;
        }
        string longestPalindrome(string s) {
            int n=s.size();
            string res;
            for(int i=0;i<n;i++){
                for(int j=i;j<n;j++){
                    string temp=s.substr(i,j-i+1);
                    if(isPalindrome(temp)&&temp.size()>res.size())
                        res=temp;
                }
            }
            return res;
        }
    };

    超时了!

    解法二(最长公共子串):

    class Solution {
    public:
        bool isPalindrome(string s) {
            int len = s.size();
            for (int i = 0; i<len; i++) {
                if (s[i] != s[len - i - 1])
                    return false;
            }
            return true;
        }
        string longestPalindrome(string s) {
            string res;
            string rev = s;
            reverse(rev.begin(), rev.end());
            if(s==rev) return s;
            for (int i = 0; i<s.size(); i++) {
                for (int j = i; j<s.size(); j++) {
                    string temp = s.substr(i, j - i + 1);
                    if(res.size()>=temp.size()) continue;
                    else if (rev.find(temp)!=string::npos ){
                         if(isPalindrome(temp)) {
                            res = temp;
                         }
                    }
                    else break;
                }
            }
            return res;
        }
    };
    
    class Solution {
    public:
        string longestPalindrome(string s) {
            string res;
            string rev = s;
            reverse(rev.begin(), rev.end());
            if(rev==s) return s;
            string temp;
            for (int i = 0; i<s.size(); i++) {
                for (int j = i; j<s.size(); j++) {
                    temp += s[j];
                    if (res.size()>=temp.size())
                        continue;
                    else if(rev.find(temp)!=string::npos){
                        string q=temp;
                        std::reverse(q.begin(),q.end());
                        if(q==temp)
                            res=temp;
                    }
                    else break;
                }
                temp="";
            }
            return res;
        }
    };
    
    

    这种方法已经通过了。

    解法三(动态规划):

    class Solution {
    public:
        string longestPalindrome(string s) {
            int len=s.length();
            if(len<2) return s;
            bool dp[len][len];
            memset(dp,0,sizeof(dp));
            string res;
            res+=s[0];                                        //最少一个字符
            for(int i=0;i<len;i++){
                dp[i][i]=1;
                if(i<len-1&&s[i]==s[i+1]){
                    dp[i][i+1]=1;
                    res=s.substr(i,2);                        //两个字符回文情况
                }
            }
            for(int l=3;l<=len;l++){
                for(int i=0;i<=len-l;i++){
                    int j=i+l-1;
                    if(s[i]==s[j]&&dp[i+1][j-1]){
                        dp[i][j]=1;
                        if(j-i+1>res.size())
                            res=s.substr(i,j-i+1);
                    }
                }
            }
            return res;
        }
    };
    
    
    
    class Solution {
    public:
        string longestPalindrome(string s) {
            int n=s.length();
            if(n<2) return s;
            vector<vector<bool>> dp(n,vector<bool>(n,0));
            int start=0,len=1;
            for(int i=0;i<n;i++){
                dp[i][i]=1;
                if(i<n-1&&s[i]==s[i+1]){
                    dp[i][i+1]=1;
                    start=i;len=2;
                }
            }
            for(int l=3;l<=n;l++){
                for(int i=0;i+l-1<n;i++){
                    int j=i+l-1;
                    if(s[i]==s[j]&&dp[i+1][j-1]){
                        dp[i][j]=1;
                        start=i;
                        len=l;
                    }
                }
            }
            return s.substr(start,len);
        }
    };
    
    
    class Solution {
    public:
        string longestPalindrome(string s) {
            int n=s.size();
            string res;
            vector<vector<bool>> dp(n,vector<bool>(n,0));
            for(int i=0;i<n;i++){                                    //开始位置
                for(int j=i;j>=0;j--){                               //中止位置
                    if(s[i]==s[j]&&(i-j<2||dp[j+1][i-1]==1)){
                        dp[j][i]=1;
                        if(i-j+1>res.size()) res=s.substr(j,i-j+1);
                    }
                }
            }
            return res;
        }
    };

    解法四(中心扩展):

    class Solution {
    public:
        int Expand(string& s, int ll, int rr) {
            if (s[ll] != s[rr]) return 1;
            while (s[ll] == s[rr]) {
                if (ll == 0 || rr == s.size() - 1)
                    break;
                else {
                    ll--;
                    rr++;
                }
            }
            return s[ll] == s[rr]? rr - ll + 1: rr - ll-1;
        }
    
        string longestPalindrome(string s) {
            int n = s.size();
            if (n<2) return s;
            int start = 0, len = 1;
            for (int i = 0; i<n - 1; i++) {
                int lenth1 = Expand(s, i, i);
                int lenth2 = Expand(s, i, i + 1);
                int temp = max(lenth1, lenth2);
                if (len<temp) {
                    start = i - (temp - 1) / 2;
                    len = temp;
                }
            }
            return s.substr(start, len);
        }
    };

    解法五(Manacher 算法,马拉车算法):

    这是一个专门用作处理最长回文子串的方法,思想很巧妙,比较难以理解,这里直接借用了别人的讲解方法。其实主要思想是,把给定的字符串的每一个字母当做中心,向两边扩展,这样来找最长的子回文串,这个叫中心扩展法,但是这个方法还要考虑到处理 abba 这种偶数个字符的回文串。Manacher 法将所有的字符串全部变成奇数个字符。

    有时间研究一下!

    214. 最短回文串

    题目描述:

    解法一(暴力解法):

    class Solution {
    public:
        string shortestPalindrome(string s) {
            int n=s.size();
            if(n<2) return s;
            int len=1;
            string res;
            string temp;
            for(int i=0;i<n;i++){
                temp+=s[i];
                string rev=temp;
                reverse(rev.begin(),rev.end());
                if(rev==temp)
                    len=temp.size();
            }
            res=s.substr(len,n-len);
            reverse(res.begin(),res.end());
            return res+s;
        }
    };
    
    
    class Solution {
    public:
        string shortestPalindrome(string s) {
            int n=s.size();
            string rev=s;
            reverse(rev.begin(),rev.end());
            for(int i=0;i<n;i++){
                if(s.substr(0,n-i)==rev.substr(i))
                    return rev.substr(0,i)+s;
            }
            return "";
        }
    };

    超时了!

    解法二(双指针减少搜索长度):

    class Solution {
    public:
        string shortestPalindrome(string s) {
            int n=s.size();
            int i=0;
            for(int j=n-1;j>=0;j--){
                if(s[j]==s[i])
                    i++;
            }
            if(i==n)
                return s;
            string revlast=s.substr(i);
            reverse(revlast.begin(),revlast.end());
            return revlast+shortestPalindrome(s.substr(0,i))+s.substr(i);
        }
    };

    解法三(KMP算法):

    KMP算法是一个时间复杂度为 O(n+m) 的字符串匹配算法,其中 n 和 m 分别是待匹配文本和字符串的长度。KMP算法的核心是部分匹配表(查找表)f(s)。

    有时间研究一下

    336. 回文对

    题目描述:

    解法:

    四种情况:

    1. 数组里有空字符串,并且数组里还有自己就是回文的字符串,每出现一个可与空字符串组成两对。(可并入3,4)
    2. 如果自己的翻转后的字符串也在数组里,可以组成一对,注意翻转后不能是自己。
    3. 如果某个字符串能找到一个分割点,分割点前的部分是回文,后半部分翻转后也在数组里,可组成一对。
    4. 把3反过来,如果后部分是回文,前半部分翻转后在数组里,可组成一对。
    class Solution {
    public:
        bool isPalindrome(string& s,int i,int j){
            while(i<j){
                if(s[i]!=s[j])
                    return false;
                i++;j--;
            }
            return true;
        }
        vector<vector<int>> palindromePairs(vector<string>& words) {
            int n=words.size();
            unordered_map<string,int> mp;        //先把每个字符串对应的位置对应起来
            set<int> lens;                       //用来搜索可以匹配够成回文的串
            vector<vector<int>> res;
            for(int i=0;i<n;i++){
                mp[words[i]]=i;
                lens.insert(words[i].size());
            }
            for(int i=0;i<n;i++){
                int len=words[i].size();
                string rev=words[i];
                reverse(rev.begin(),rev.end());        
                if(mp.count(rev)&&mp[rev]!=i)                    //整个串与其他串构成回文,对应方式2
                    res.push_back(vector<int>{i,mp[rev]});
                auto pos=lens.find(len);
                for(auto it=lens.begin();it!=pos;it++){   //串的前段或者后端的一部分与其他串构成回文,其他串长度必然小于当前串
                    if(isPalindrome(words[i],0,len-*it-1)&&mp.count(rev.substr(0,*it))){ //两种构成回文的方式  对应方式3
                        res.push_back(vector<int>{mp[rev.substr(0,*it)],i});
                    }
                    if(isPalindrome(words[i],*it,len-1)&&mp.count(rev.substr(len-*it,*it))){  //对应方式4
                        res.push_back(vector<int>{i,mp[rev.substr(len-*it)]});
                    }
                }
            }
            return res;
        }
    };

    131. 分割回文串

    题目描述:

    解法一(回溯):

    class Solution {
    public:
        bool isPalindrome(string& s, int l, int r) {    //判断[l,r]之间是否位回文
            while (l<r) {
                if (s[l++] != s[r--])
                    return false;
            }
            return true;
        }
        void helper(vector<vector<string>>& res, string& s, int ll, int rr, vector<string>& temp) {
            if (ll == rr) res.push_back(temp);
            for (int len = 1; len <= rr - ll; len++) {        //以长度为标尺,长度扩大
                if (isPalindrome(s, ll, ll + len - 1)) {
                    temp.push_back(s.substr(ll, len));
                    helper(res, s, ll + len, rr, temp);
                    temp.erase(temp.end() - 1);
                }
            }
        }
        vector<vector<string>> partition(string s) {
            vector<vector<string>> res;
            vector<string> temp;
            helper(res, s, 0, s.size(), temp);
            return res;
        }
    };

    解法二(dfs+回溯):

    class Solution {
    public:
        void DFS(string& s, vector<vector<string>>& res, vector<string>& temp, vector<vector<bool>>& dp, int index) {
            if (index == s.size()) {
                res.push_back(temp);
            }
            for (int i = index; i<s.size(); i++) {
                if (dp[index][i]) {
                    temp.push_back(s.substr(index, i - index + 1));
                    DFS(s, res, temp, dp, i + 1);
                    temp.pop_back();
                }
            }
        }
        vector<vector<string>> partition(string s) {
            int n = s.size();
            vector<vector<bool>> dp(n, vector<bool>(n, 0));
            for (int i = 0; i<n; i++) {
                for (int j = i; j >= 0; j--) {
                    if (s[i] == s[j] && (i - j<2 || dp[j + 1][i - 1]))
                        dp[j][i] = 1;
                }
            }
            vector<vector<string>> res;
            vector<string> temp;
            DFS(s, res, temp, dp, 0);
            return res;
        }
    };
    
    
    class Solution {
    public:
        bool dp[1001][1001] = { 0 };
    	vector<vector<string>> res;
    	vector<string> tmp;
    	vector<vector<string>> partition(string s) {
    		int l = s.length();
    		//两个for循环构造回文串的dp数组
    		for (int i = 0; i < l; i++) {
    			for (int j = 0; j <= i; j++) {
    				if (s[i] == s[j] && (i - j < 2 || dp[j + 1][i - 1]))
    					dp[j][i] = 1;
    			}
    		}
    		dfs(0, l, s);
    		return res;
    
    	}
    
    	void dfs(int i,int n,string s) {
    		if (i == n) res.push_back(tmp);
    		for (int j = i; j < n; j++) {
    			if (dp[i][j]) {
    				tmp.push_back(s.substr(i, j-i+1));
    				dfs(j + 1, n, s);
    				tmp.erase(tmp.end() - 1);
    			}
    		}
    	}
    };

    132. 分割回文串 II

    题目描述:

    解法:

    class Solution {
    public:
        int minCut(string s) {
            int n=s.size();
            vector<vector<bool>> dp(n,vector<bool>(n,0));
            vector<int> res(n+1,INT_MAX);
            res[0]=-1;
            for(int i=0;i<n;i++){
                for(int j=i;j>=0;j--){
                    if(s[i]==s[j]&&(i-j<2||dp[j+1][i-1])){
                        dp[j][i]=1;
                        res[i+1]=min(res[i+1],1+res[j]);
                    }
                }
            }
            return res[n];
        }
    };
    
    class Solution {
    public:
        int minCut(string s) {
            int n=s.size();
            vector<vector<bool>> dp(n,vector<bool>(n,0));
            vector<int> res(n,INT_MAX);
            for(int i=0;i<n;i++){
                for(int j=0;j<=i;j++){
                    if(s[i]==s[j]&&(i-j<2||dp[j+1][i-1])){
                        dp[j][i]=1;
                        if(j==0) res[i]=0;
                        else res[i]=min(res[i],1+res[j-1]);
                    }
                }
            }
            return res[n-1];
        }
    };
  • 相关阅读:
    MVC视图展现模式之移动布局解析-续集
    网站就必须用响应式布局吗?MVC视图展现模式之移动布局
    用Word写博客园文章
    扩:new and override
    通告
    List-style-type属性失效
    在线浏览PDF之PDF.JS (附demo)
    08. Web大前端时代之:HTML5+CSS3入门系列~H5 Web存储
    07. Web大前端时代之:HTML5+CSS3入门系列~H5 地理位置
    06. Web大前端时代之:HTML5+CSS3入门系列~HTML5 画布
  • 原文地址:https://www.cnblogs.com/oneDongHua/p/14263988.html
Copyright © 2020-2023  润新知