import java.util.*; /** * NC228 判断子序列 * @author d3y1 */ public class Solution { /** * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可 * * * @param S string字符串 * @param T string字符串 * @return bool布尔型 */ public boolean isSubsequence (String S, String T) { // return solution1(S,T); return solution11(S,T); // return solution2(S,T); // return solution22(S,T); // return solution3(S,T); // return solution33(S,T); // return solution4(S,T); // return solution44(S,T); } /** * 双指针 * @param S * @param T * @return */ private boolean solution1(String S, String T){ int lenS = S.length(); int lenT = T.length(); if(lenS > lenT){ return false; } // 双指针 int i = 0; int j = 0; while(i<lenS && j<lenT){ if(S.charAt(i) == T.charAt(j)){ i++; j++; }else{ j++; } } return i==lenS; } /** * 双指针 * @param S * @param T * @return */ private boolean solution11(String S, String T){ int lenS = S.length(); int lenT = T.length(); if(lenS > lenT){ return false; } // 双指针 for(int i=0,j=0; i<lenS&&j<lenT; j++){ if(S.charAt(i) == T.charAt(j)){ i++; } if(i == lenS){ return true; } } return false; } /** * 动态规划: 二维数组 * * 转化为: 最长公共子序列问题 * * dp[i][j]表示S以第i个字符结尾(S[0,i-1])且T以第j个字符结尾(T[0,j-1])的最长公共子序列的长度 * * { dp[i-1][j-1] + 1 , S.charAt(i-1) == T.charAt(j-1) * dp[i][j] = { * { Math.max(dp[i-1][j], dp[i][j-1]) , S.charAt(i-1) != T.charAt(j-1) * * @param S * @param T * @return */ private boolean solution2(String S, String T){ int lenS = S.length(); int lenT = T.length(); if(lenS > lenT){ return false; } int[][] dp = new int[lenS+1][lenT+1]; for(int i=1; i<=lenS; i++){ for(int j=1; j<=lenT; j++){ if(S.charAt(i-1) == T.charAt(j-1)){ dp[i][j] = dp[i-1][j-1] + 1; }else{ dp[i][j] = Math.max(dp[i-1][j], dp[i][j-1]); } } } return dp[lenS][lenT]==lenS; } /** * 动态规划: 二维数组 * * 转化为: 最长公共子序列问题 * * dp[i][j]表示S以第i个字符结尾(S[0,i-1])且T以第j个字符结尾(T[0,j-1])的最长公共子序列的长度 * * { dp[i-1][j-1] + 1 , S.charAt(i-1) == T.charAt(j-1) * dp[i][j] = { * { Math.max(dp[i-1][j], dp[i][j-1]) , S.charAt(i-1) != T.charAt(j-1) * * @param S * @param T * @return */ private boolean solution22(String S, String T){ int lenS = S.length(); int lenT = T.length(); if(lenS > lenT){ return false; } int[][] dp = new int[lenS+1][lenT+1]; for(int i=1; i<=lenS; i++){ for(int j=1; j<=lenT; j++){ if(S.charAt(i-1) == T.charAt(j-1)){ dp[i][j] = dp[i-1][j-1] + 1; }else{ dp[i][j] = Math.max(dp[i-1][j], dp[i][j-1]); } } // S[0,i-1]不是T的子序列 if(dp[i][lenT] < i){ return false; } } return true; } /** * 动态规划: 一维数组(空间优化) * * 转化为: 最长公共子序列问题 * * dp[j]表示T以第j个字符结尾(T[0,j-1])时的最长公共子序列的长度 * * { pre + 1 , S.charAt(i-1) == T.charAt(j-1) * dp[j] = { * { Math.max(dp[j-1], dp[j]) , S.charAt(i-1) != T.charAt(j-1) * * @param S * @param T * @return */ private boolean solution3(String S, String T){ int lenS = S.length(); int lenT = T.length(); if(lenS > lenT){ return false; } int[] dp = new int[lenT+1]; for(int i=1; i<=lenS; i++){ int pre = 0; for(int j=1; j<=lenT; j++){ int tmp = dp[j]; if(S.charAt(i-1) == T.charAt(j-1)){ dp[j] = pre + 1; }else{ dp[j] = Math.max(dp[j-1], dp[j]); } pre = tmp; } } return dp[lenT]==lenS; } /** * 动态规划: 一维数组(空间优化) * * 转化为: 最长公共子序列问题 * * dp[j]表示T以第j个字符结尾(T[0,j-1])时的最长公共子序列的长度 * * { pre + 1 , S.charAt(i-1) == T.charAt(j-1) * dp[j] = { * { Math.max(dp[j-1], dp[j]) , S.charAt(i-1) != T.charAt(j-1) * * @param S * @param T * @return */ private boolean solution33(String S, String T){ int lenS = S.length(); int lenT = T.length(); if(lenS > lenT){ return false; } int[] dp = new int[lenT+1]; for(int i=1; i<=lenS; i++){ int pre = 0; for(int j=1; j<=lenT; j++){ int tmp = dp[j]; if(S.charAt(i-1) == T.charAt(j-1)){ dp[j] = pre + 1; }else{ dp[j] = Math.max(dp[j-1], dp[j]); } pre = tmp; } // S[0,i-1]不是T的子序列 if(dp[lenT] < i){ return false; } } return true; } /** * 动态规划: 二维数组 * * dp[i][j]表示S[0,i-1]是否为T[0,j-1]的子序列 * * { dp[i][j-1] | dp[i-1][j-1] , S.charAt(i-1) == T.charAt(j-1) * dp[i][j] = { * { dp[i][j-1] , S.charAt(i-1) != T.charAt(j-1) * * @param S * @param T * @return */ private boolean solution4(String S, String T){ int lenS = S.length(); int lenT = T.length(); if(lenS > lenT){ return false; } boolean[][] dp = new boolean[lenS+1][lenT+1]; // 空串一定是T的子序列 for(int j=0; j<=lenT; j++){ dp[0][j] = true; } for(int i=1; i<=lenS; i++){ for(int j=1; j<=lenT; j++){ if(S.charAt(i-1) == T.charAt(j-1)){ dp[i][j] = dp[i][j-1] | dp[i-1][j-1]; }else{ dp[i][j] = dp[i][j-1]; } } } return dp[lenS][lenT]; } /** * 动态规划: 二维数组 * * dp[i][j]表示S[0,i-1]是否为T[0,j-1]的子序列 * * { dp[i][j-1] | dp[i-1][j-1] , S.charAt(i-1) == T.charAt(j-1) * dp[i][j] = { * { dp[i][j-1] , S.charAt(i-1) != T.charAt(j-1) * * @param S * @param T * @return */ private boolean solution44(String S, String T){ int lenS = S.length(); int lenT = T.length(); if(lenS > lenT){ return false; } boolean[][] dp = new boolean[lenS+1][lenT+1]; // 空串一定是T的子序列 for(int j=0; j<=lenT; j++){ dp[0][j] = true; } for(int i=1; i<=lenS; i++){ for(int j=1; j<=lenT; j++){ if(S.charAt(i-1) == T.charAt(j-1)){ dp[i][j] = dp[i][j-1] | dp[i-1][j-1]; }else{ dp[i][j] = dp[i][j-1]; } } // S[0,i-1]不是T的子序列 if(!dp[i][lenT]){ return false; } } return true; } }