题目描述
解题思路
- dp数组含义
 
dp[i][j] 表示以下标i-1为结尾的字符串s,和以下标j-1为结尾的字符串t,相同子序列的长度为dp[i][j]。
- 确定递推公式
 
在确定递推公式的时候,首先要考虑如下两种操作,整理如下:
- if (s[i - 1] == t[j - 1])
- t中找到了一个字符在s中也出现了,此时就是s[i-2]和t[j-2]的子序列长度加一。dp[i][j] = dp[i - 1][j - 1] + 1;
 
 - if (s[i - 1] != t[j - 1])
- 相当于t要删除元素,继续匹配,此时应该就是s[j-2]的子序列长度,即dp[i][j] = dp[i][j - 1];
- 初始化
 
 
 - 相当于t要删除元素,继续匹配,此时应该就是s[j-2]的子序列长度,即dp[i][j] = dp[i][j - 1];
 
可以由题推出,如果哪一边长度为0,那么子序列长度也就是0。所以都初始化为0。
- 遍历顺序
 
同理从递推公式可以看出dp[i][j]都是依赖于dp[i - 1][j - 1] 和 dp[i][j - 1],那么遍历顺序也应该是从上到下,从左到右
- 举例推导dp数组
 
以示例一为例,输入:s = “abc”, t = “ahbgdc”,dp状态转移图如下:
 dp[i][j]表示以下标i-1为结尾的字符串s和以下标j-1为结尾的字符串t 相同子序列的长度,所以如果dp[s.size()][t.size()] 与 字符串s的长度相同说明:s与t的最长相同子序列就是s,那么s 就是 t 的子序列。
图中dp[s.size()][t.size()] = 3, 而s.size() 也为3。所以s是t 的子序列,返回true。
最后判断如果相同子序列长度等于s的长度,那么s就是t的子序列。
public boolean isSubsequence(String s, String t) {// dp[i][j]表示以下标i-1为结尾的字符串s,和以下标j-1为结尾的字符串t,相同子序列的长度为dp[i][j]int[][] dp = new int[s.length() + 1][t.length() + 1];// 初始化左上两边for (int i = 0; i < s.length() + 1; i++) {dp[i][0] = 0;}for (int i = 0; i < t.length() + 1; i++) {dp[0][i] = 0;}for (int i = 1; i < s.length() + 1; i++) {for (int j = 1; j < t.length() + 1; j++) {// if (s[i - 1] == t[j - 1])// t中找到了一个字符在s中也出现了// if (s[i - 1] != t[j - 1])// 相当于t要删除元素,继续匹配if (s.charAt(i - 1) == t.charAt(j - 1)) {dp[i][j] = dp[i - 1][j - 1] + 1; // 相同子序列数加一,表示s中又有一个字母在t中} else {dp[i][j] = dp[i][j - 1]; // 不相等时,子序列的长度不变}}}return dp[s.length()][t.length()] == s.length() ? true : false;}
