524.通过删除字母匹配到字典里最长单词

题目

给你一个字符串 s 和一个字符串数组 dictionary 作为字典,找出并返回字典中最长的字符串,该字符串可以通过删除 s 中的某些字符得到。

如果答案不止一个,返回长度最长且字典序最小的字符串。如果答案不存在,则返回空字符串。

示例 1:

输入:s = “abpcplea”, dictionary = [“ale”,”apple”,”monkey”,”plea”]
输出:“apple”

示例 2:

输入:s = “abpcplea”, dictionary = [“a”,”b”,”c”]
输出:“a”

提示:

  • 1 <= s.length <= 1000
  • 1 <= dictionary.length <= 1000
  • 1 <= dictionary[i].length <= 1000
  • sdictionary[i] 仅由小写英文字母组成

    思路

    暴力求解。
    对于dictionary~i~,按照顺序与s进行比较,看看dictionary~i~在s中是否能够按顺序都找到。如果能找到,就比较长度,长度相等则比较字典序。

    代码

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    class Solution {
    public:
    string findLongestWord(string s, vector<string>& dictionary) {
    int res_id = -1;
    for(int i=0;i<dictionary.size();++i){
    if(dictionary[i].length()>s.length()) continue;
    int j=0;
    for(int k=0;k<s.size();++k){
    if(s[k]==dictionary[i][j]) j++;
    }
    if(j!=dictionary[i].length()) continue;
    if(res_id==-1||
    dictionary[i].length()>dictionary[res_id].length()||
    (dictionary[i].length()==dictionary[res_id].length()&&dictionary[i]<dictionary[res_id])){
    res_id = i;
    }
    }
    if(res_id==-1) return "";
    return dictionary[res_id];
    }
    };

516.最长回文子序列

题目

516. 最长回文子序列 - 力扣(LeetCode) (leetcode-cn.com)

给你一个字符串 s ,找出其中最长的回文子序列,并返回该序列的长度。

子序列定义为:不改变剩余字符顺序的情况下,删除某些字符或者不删除任何字符形成的一个序列.

实例1:

输入:s = “bbbab”
输出:4
解释:一个可能的最长回文子序列为 “bbbb” 。

示例 2:

输入:s = “cbbd”
输出:2
解释:一个可能的最长回文子序列为 “bb” 。

思路

  • 马拉车

    马拉车算法用来解决最长回文字串的问题是最先想到的思路,但是本地比较特殊的一点在于,可以删除。如果分别删除,复杂度会太大,因此排除使用马拉车算法的思路。

  • 动态规划

    设置数组dpdp[i][j]代表从s[i]s[j] 的最长回文字串长度。

    初始状态: dp[i][i]=1

    中间状态:对于任意i,j 0<=i<j<n,其中任意字串的长度都已经通过循环获得。这里让j从0开始循环的,因此0~j-1内的所有字串的最大回文长度都已经知道,从0~j相当于在此基础上在最后一位上加上了s[j]。令ij-1开始向0 循环,这样整体的长度才是从小往大:

    • 如果s[i]==s[j],那么就是i+1~j-1内最大的回文字串长度加上2:

      dp[i][j]=dp[i+1][j-1]+2
      如果`s[i]==s[j]`但是`dp[i+1][j-1]`并不是从`i+1`开始到`j-1`结束的回文字串呢?没有关系,中间的可以都删除,因此只需要保存最长的长度即可。
  • 如果s[i]!=s[j],那么只需要dp[i][j]设置为i~j-1i+1~j中的最长回文字串长度即可:

    dp[i][j]=max(dp[i][j-1],dp[i+1][j])

由于是从头往后开始遍历的,因此遍历到i的时候再将dp[i][j]设置为1即可。

结果: dp[i][j]代表从s[i]s[j] 的最长回文字串长度。因此s0n-1的最长回文字串长度就是dp[0][n-1]

代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
class Solution {
public:
int longestPalindromeSubseq(string s) {
int n = s.length();
int dp[n][n];
memset(dp,0,sizeof(int)*n*n);
for(int i=0;i<n;i++){
dp[i][i] = 1;
for(int j=i-1;j>=0;j--){
if(s[i]==s[j]){
dp[j][i] = dp[j+1][i-1]+2;
}else{
dp[j][i] = max(dp[j][i-1],dp[j+1][i]);
}
}
}
return dp[0][n-1];
}
};