Leecode392.判断子序列

题目描述:   

        给定字符串 s 和 t ,判断 s 是否为 t 的子序列。字符串的一个子序列是原始字符串删除一些(也可以不删除)字符而不改变剩余字符相对位置形成的新字符串。(例如,"ace"是"abcde"的一个子序列,而"aec"不是)。

进阶:

        如果有大量输入的 S,称作 S1, S2, ... , Sk 其中 k >= 10亿,你需要依次检查它们是否为 T 的子序列。在这种情况下,你会怎样改变代码?
        链接:https://leetcode-cn.com/problems/is-subsequence

解法一及解析:

class solution{
    public void isSubsequence(String s,String t){
        /*
        思路:   遍历t,与s的每一个字符进行对比,
                如果匹配成功,则进行s下一个字符的匹配,
                如果s所有的字符都进行了匹配,那么说明s是t的子序列
        */
        int j=0;
        for(int i=0;i

解析:

        解法1思路简单,时间复杂度小O(n),空间复杂度O(1),如果单次检测性能高,但是如果有很多个s需要进行,每次都需要进行t遍历,那么效果会很低,从解法一中我们可以看出,性能优化点在遍历字符串t上,如果我们可以记录t中每个字符出现的下标,那么就可以跳过很多字符,不用每次都遍历t。
 

解法二及解析:

        思路:预处理对于t的每一个位置,从当前下标往后每一个字符第一次出现的下标。用dp[i][j]来进行维护,dp[i][j]表示从当前下标i开始往后,字符j第一次出现的下标,状态转移:如果当前字符就等于j,那么dp[i][j]=i;如果当前字符不等于j,那么dp[i][j]=dp[i+1][j],即前一个下标开始,第一次出现的下标。

//状态转移方程
dp[i][j]=s.charAt(i)=='a'+j?i:dp[i+1][j];

        完整代码:

class solution{
    public void isSubsequence(String s,string t){
        int m=s.length,n=t.length;
        int[][] dp=new int[n+1][n+1];

        //dp数组初始化,0~25代表a~z
        for(int i=0;i<26;i++){
            //初始化含义:从下标为n开始,所有的字符都不可达
            dp[n][i]=n;
        }

        //记录String t中所有字符:
        //注意,一定到倒序遍历,因为前面下标的dp值会用到后面下标的dp值
        for(int i=n-1;i>=0;i--){
            for(int j=0;j<26;j++){
                dp[i][j]=t.charAt(i)=='a'+j?i:dp[i+1][j];
            }
        }

        //开始检测String s
        int cur=0;//记录在t中当前匹配的下标
        for(int i=0;i

你可能感兴趣的:(动态规划,leetcode)