zoukankan      html  css  js  c++  java
  • 392. 判断子序列

    题目要求s需要是t的子序列,子序列的定义是t中删除一些元素能够与s保持一致。

    类似的题目有求2个字符串的最长公共子序列,经典的DP题。

    不过本题我们可以偷懒使用双指针来处理,可以把题目简化为

    s中的每一个字符是否都能在t中找到对应

    时间O(m+n)(m、n分别为字符串s和t的长度),空间O(1)

     1     public boolean isSubsequence(String s, String t) {
     2         int i=0,j=0;
     3         while(i<s.length() && j<t.length()){
     4             if(s.charAt(i)==t.charAt(j)){
     5                 i++;
     6             }
     7             j++;
     8         }
     9         return i==s.length();
    10     }

    对于进阶问题,当我们在遇到超多字符串需要匹配时,如果我们

    还使用上面方案的话,实际比较时间将会线性上升到k*(m+n)

    于是我们可以参照KMP的next数组对字符串t做处理,

    由于题目限定了s和t都只包含了小写字母,我们可以初始化一个

    数组,存储第i个位置后出现字符j的位置,即,当我们遍历字符串

    t到第i位时,此时s对应的字符是j,需要将t中i推进至哪一位。

    这样做的好处是可以避免了s与t中字符不匹配,t中下标需要逐个递推

    造成的时间浪费。

    对于dp[i][j],我们发现只存在2种可能,(1)第i位便是j(2)第i位不是j

    对于情况1,我们有dp[i][j]=i,对于情况2,我们便需要向后查找,于是有do[i][j]=dp[i+1][j]

    由于第2种情况的存在,建立dp数组时我们需要从后向前递推

    时间O(m*26+n*k)(建立dp数组耗时m*26,逐个匹配字符串s耗时k*s),空间O(m*26)

     1 public boolean isSubsequence(String s, String t) {
     2         int n=s.length(),m=t.length();
     3         int[][] dp=new int[m+1][26];
     4         
     5         // 初始化边界值,dp[i][j] = m表示t中不存在字符j
     6         for(int i=0;i<26;i++){
     7             dp[m][i] = m;
     8         }
     9 
    10         for(int i=m-1;i>=0;i--){
    11             for(int j=0;j<26;j++){
    12                 // 从后向前递推,存在2种情况,t中第i个位置是j,那么
    13                 // dp[i][j]=i,否则就要向后查找,于是有dp[i][j]=dp[i+1][j]
    14                 if(t.charAt(i)==j+'a'){
    15                     dp[i][j]=i;
    16                 }else{
    17                     dp[i][j]=dp[i+1][j];
    18                 }
    19             }
    20         }
    21 
    22         int index=0;
    23         for(int i=0;i<n;i++){
    24             // 表示在t的剩余空间内没有再出现s中的字符,直接返回
    25             if(dp[index][s.charAt(i)-'a']==m){
    26                 return false;
    27             }
    28             // 成功匹配,则继续往后查找
    29             index=dp[index][s.charAt(i)-'a']+1;
    30         }
    31 
    32         return true;
    33     }
    争取早日不再是一只菜鸡
  • 相关阅读:
    bzoj1660[Usaco2006 Nov]Bad Hair Day 乱发节*
    bzoj1624[Usaco2008 Open] Clear And Present Danger 寻宝之路*
    bzoj1617[Usaco2008 Mar]River Crossing渡河问题*
    bzoj1681[Usaco2005 Mar]Checking an Alibi 不在场的证明*
    bzoj1631[Usaco2007 Feb]Cow Party*
    bzoj1854[Scoi2010]游戏
    bzoj2338[HNOI2011]数矩形
    bzoj1096[ZJOI2007]仓库建设
    继承原理、派生重用
    面向对象三大特性——继承(含派生)
  • 原文地址:https://www.cnblogs.com/jchen104/p/14738611.html
Copyright © 2011-2022 走看看