题目描述
给定字符串 s 和 t ,判断 s 是否为 t 的子序列。
你可以认为 s 和 t 中仅包含英文小写字母。字符串 t 可能会很长(长度 ~= 500,000),而 s 是个短字符串(长度 <=100)。
字符串的一个子序列是原始字符串删除一些(也可以不删除)字符而不改变剩余字符相对位置形成的新字符串。(例如,"ace"是"abcde"的一个子序列,而"aec"不是)。
示例 1:
s = “abc”, t = “ahbgdc”
返回 true.
示例 2:
s = “axc”, t = “ahbgdc”
返回 false.
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/is-subsequence
题解
既然题目有动态规划的tag,这道题就来练练DP吧。(PS:其他方法肯定比DP快,只是一题多解哈)
思路:
状态:dp[i][j]为s的从头开始到i的子字符串是否为t从头开始到j的子字符串的子序列
状态转移公式:
- 当char[i]==char[j]时,则字符i一定是j的子序列,如果0 ~ i-1子字符串是0 ~ j-1子字符串的子序列,则dp[i][j]=true,所以dp[i][j] = dp[i-1][j-1];
- 当char[i]!=char[i]时,即判断当前0 ~ i子字符串是否是0 ~ j-1的子字符串的子序列,即dp[i][j] = dp[i][j - 1]。如ab,eabc,虽然s的最后一个字符和t中最后一个字符不相等,但是因为ab是eab的子序列,所以ab也是eabc的子序列
初始化:空字符串一定是t的子字符串的子序列,所以dp[0][j]=true
结果:返回dp[sLen][tLen]
class Solution {
public boolean isSubsequence(String s, String t) {
int sLen = s.length(), tLen = t.length();
if (sLen > tLen) return false;
if (sLen == 0) return true;
boolean[][] dp = new boolean[sLen + 1][tLen + 1];
//初始化
for (int j = 0; j < tLen; j++) {
dp[0][j] = true;
}
//dp
for (int i = 1; i <= sLen; i++) {
for (int j = 1; j <= tLen; j++) {
if (s.charAt(i - 1) == t.charAt(j - 1)) {
dp[i][j] = dp[i - 1][j - 1];
} else {
dp[i][j] = dp[i][j - 1];
}
}
}
return dp[sLen][tLen];
}
}
我的写法
比别人麻烦了一点
class Solution {
public boolean isSubsequence(String s, String t) {
int m = s.length();
int n = t.length();
boolean[][] dp = new boolean[m][n];
if(s.length()==0)
return true;
if(t.length()==0)
return false;
if(s.charAt(0) == t.charAt(0))
{
dp[0][0] = true;
}
else
{
dp[0][0] = false;
}
for(int i=1;i<n;i++)
{
if(s.charAt(0) == t.charAt(i))
{
dp[0][i] = true;
}
else
{
dp[0][i] = dp[0][i-1];
}
}
for(int i=1;i<m;i++)
{
dp[i][0] = false;
}
for(int i = 1;i<m;i++)
{
for(int j=1;j<n;j++)
{
if(s.charAt(i) == t.charAt(j))
{
dp[i][j] = dp[i-1][j-1];
}
else
{
dp[i][j] = dp[i][j-1];
}
}
}
return dp[m-1][n-1];
}
}