最长公共子串、最长公共子序列、最长回文子串、最长回文子序列、回文子串个数

来源:互联网 发布:flash mac版下载 编辑:程序博客网 时间:2024/06/04 18:27

1、最长公共子串

首先看最长公共子串的解答(暴力算法、动态规划、)
从优化到再优化,最长公共子串

2、最长公共子序列(LCS) 

解析:动态规划解最长公共子序列问题


3、 leetcode 5 Longest Palindromic Substring 最长回文串

方法1:借助最长公共子串问题,将原来的string翻转,求两个字符串的最长公共子串,但是可能出现的情况是S=”abacdfgdcaba”S' = \textrm{''abacdgfdcaba''}S方法2:暴力算法
调出所有的子串比较是否是回文串
方法3: 动态规划
P(i,j)P(i,j) as following:P(i,j)={true,false,if the substring SiSj is a palindromeotherwise. true,false,if the substring SiSj is a palindromeotherwise. P(i, j) = ( P(i+1, j-1) \text{ and } S_i == S_j )P(i,j)=(P(i+1,j1) and Sii
==Sjj
)P(i, i) = trueP(i,i)=trueP(i, i+1) = ( S_i == S_{i+1} )P(i,i+1)=(Sii
==Si+1i+1
)事件复杂度和空间复杂度都是n2
方法4: 自中心扩展 没有动态规划数组,时间复杂度仍然是n2,空间复杂度是1
每个字符串都有一个中心,一共有2n-1个中心。回文串是偶数的时候,中心在两个字符之间

class Solution {public:    string longestPalindrome(string s) {        //使用第四个方法,自中心扩展        int start=0,end=0;//保存当前最长回文串的起始和终结位置        for(int i=0;i<s.size();i++)        {            int len1=expandFromCenter(s,i,i);//以当前字符为中心的回文串(奇数)            int len2=expandFromCenter(s,i,i+1);//以当前和下一个字符的中间为中心的回文串(偶数)            int len=max(len1,len2);            if(len>end-start+1)//如果求得的新字符串长度是比之前保存的要长的话            {                 start=i-(len-1)/2;                end=i+len/2;            }        }        return s.substr(start,end-start+1);//注意这个函数的用法,是首地址和字符串的长度    }    int expandFromCenter(string& s,int left,int right){        while(left>=0&&right<=s.size()&&s[left]==s[right]){//这种书写方式考虑到奇数和偶数的情况            --left;            ++right;        }        return right-left-1;//返回长度,因为right和left都是移到了回文串的外围位置    }      };
马拉车算法:


516. Longest Palindromic Subsequence 最长回文子序列


dp算法:
dp[i][j]指的是i,j之间的最大回文子序列
有:

if i == j, then longest[i][j] = 1, naturally
if i+1 == j, then longest[i][j] = 2 if s[i] == s[j]
longest[i][j] = 1 otherwise
Transition rule:

  1. s[i] == s[j]
    dp[i][j] = max(dp[i+1][j], dp[i][j-1], dp[i+1][j-1] + 2)
  2. s[i] != s[j]
    dp[i][j] = max(dp[i+1][j], dp[i][j-1], dp[i+1][j-1])
注意:循环的时候要注意次序,外循环是字符串的长度(从1到n),内循环是起始位置,这样才能保证迭代公式中的值都是更新后的。
class Solution {public:    //lhs means left hand side, rhs means right hand side    int longestPalindromeSubseq(string s) {        if (s.empty()) return 0;                vector<vector<int>> longest(s.size(), vector<int>(s.size()));        for (int len=1; len<=s.size(); len++) {            for (int lhs=0; lhs+len<=s.size(); lhs++) {                int rhs = lhs+len-1;                if (lhs == rhs) {                    longest[lhs][rhs] = 1;                } else if (lhs+1 == rhs) {                    longest[lhs][rhs] = (s[lhs] == s[rhs]) ? 2 : 1;                } else {                    int add = s[lhs] == s[rhs] ? 2 : 0;                    longest[lhs][rhs] = max(max(longest[lhs][rhs-1], longest[lhs+1][rhs]), longest[lhs+1][rhs-1] + add);                }            }        }                return longest[0].back();    }};

另外一种循环方式:
class Solution {public:    int longestPalindromeSubseq(string s) {       int n=s.size();        vector<vector<int>> dp(n,vector<int>(n,0));        for(int i=n-1;i>=0;i--)        {            dp[i][i]=1;           for(int j=i+1;j<n;j++)            {                if(s[i]==s[j])                    dp[i][j]=dp[i+1][j-1]+2;               else                   dp[i][j]=max(dp[i+1][j],dp[i][j-1]);            }         }        return dp[0][n-1];                }};

647. Palindromic Substrings 统计回文子串的个数

Given a string, your task is to count how many palindromic substrings in this string.

The substrings with different start indexes or end indexes are counted as different substrings even they consist of same characters.

Example 1:

Input: "abc"Output: 3Explanation: Three palindromic strings: "a", "b", "c".

Example 2:

Input: "aaa"Output: 6Explanation: Six palindromic strings: "a", "a", "a", "aa", "aa", "aaa".

Note:

  1. The input string length won't exceed 1000.
自己的解法:与516类似
class Solution {public:    int countSubstrings(string s) {        int sum=0;        int n=s.size();        if(n==0) return 0;        vector<vector<bool>> dp(n,vector<bool>(n,false));        for(int i=n-1;i>=0;i--)        {            dp[i][i]=true;            sum++;            for(int j=i+1;j<n;j++)            {                if(s[i]==s[j])                {                    if(i+1==j||dp[i+1][j-1])                    {                        dp[i][j]=true;                        sum++;                    }                }                else dp[i][j]=false;            }        }        return sum;    }};

214. Shortest Palindrome 最短回文串

给定一个字符串,在它前面添加字符,组成一个最短的回文串

Given a string S, you are allowed to convert it to a palindrome by adding characters in front of it. Find and return the shortest palindrome you can find by performing this transformation.

For example:

Given "aacecaaa", return "aaacecaaa".

Given "abcd", return "dcbabcd".

使用KMP算法 放一放

其他相关:

242. Valid Anagram

Given two strings s and t, write a function to determine if t is an anagram of s.

For example,
s = "anagram", t = "nagaram", return true.
s = "rat", t = "car", return false.

Note:
You may assume the string contains only lowercase alphabets.

Follow up:
What if the inputs contain unicode characters? How would you adapt your solution to such case?

class Solution {
public:
    bool isAnagram(string s, string t) {
        vector<int> flag(256,0);
        if(s.size()!=t.size()) return false;
        for(int i=0;i<s.size();i++)
            flag[s[i]]++;
        for(int i=0;i<s.size();i++)
        {
            if(flag[t[i]]==0) return false;
            flag[t[i]]--;
        }
        if(find_if(flag.begin(),flag.end(),com)!=flag.end()) return false;
        return true;
    }
    static bool com(const int s){
        return s>0?true:false;
    }
};


classSolution {public:boolisAnagram(string s,string t){if (s.length() != t.length()) returnfalse;int n = s.length(); unordered_map<char,int> counts; for (int i = 0; i < n; i++) { counts[s[i]]++; counts[t[i]]--; } for (auto count : counts) if (count.second) returnfalse;returntrue; }};
阅读全文
0 0