• LeetCode_Distinct Subsequences


    Given a string S and a string T, count the number of distinct subsequences of T in S.
    
    A subsequence of a string is a new string which is formed from the original string by deleting some (can be none) of the characters without disturbing the relative positions of the remaining characters. (ie, "ACE" is a subsequence of "ABCDE" while "AEC" is not).
    
    Here is an example:
    S = "rabbbit", T = "rabbit"
    
    Return 3.
    

      

    class Solution {
    public:
            
        
        void DFS(string S, string T,int si,int num, vector<char> &tp)
        {
           
          if(num == sizeB){
                 answer ++;
                 return ;
          }
          
          if(si >= sizeA || num > sizeB)
             return ;
        
          for(int i = si; i<sizeA ; i++)
          {
              if(S[i] == T[num])
                {
             tp.push_back(S[i]) ;
             DFS(S,T,i+1, num+1, tp);
             tp.pop_back() ;
             
             }
          }
        }
        int numDistinct(string S, string T) {
            // Start typing your C/C++ solution below
            // DO NOT write int main() function
            sizeA = S.size();
            sizeB = T.size();
            
            if(sizeA < sizeB) return 0;
            
             answer = 0;
             int i;
             for( i=0 ; i< sizeA  ; i++)
                   if(S[i] == T[0])
                      break ;
             
             if(i < sizeA)
             {
             
               vector<char> tp;
               DFS(S,T,i,0,tp) ;
              
              }
              
              return answer;
        }
    private :
      int answer ;
      int sizeA;
      int sizeB;
     
    };

    上述代码使用DFS来做,大数据还过不了

    DP:

    将“S串中前m个字母的子串中包含多少个T串中前n个字母的子串”这样的问题记为A[m][n]。 可以得到递推式 :
    if(S[m-1] == T[n-1]) A[m][n] = A[m-1][n-1] + A[m-1][n];
    else A[m][n] = A[m-1][n-1];
    再处理边界情况即可。简单起见,用类似打表记录式的递归实现。

    class Solution {
    public:
            
        int Dp(int m, int n, int *tp, const string &S,const string & T )
        {
          
           if(n == -1) return 1;
            else if(m == -1) return 0;
            
            if(m < n) return 0;
           if( tp[m*sizeB+n] != -1 )
             return tp[m*sizeB+n];
             
            tp[m*sizeB+n] =  S[m] == T[n] ? Dp(m-1, n-1,tp, S, T) + Dp(m-1, n,tp,S,T) :
                                Dp(m-1, n,tp,S,T) ;
        
            return tp[m*sizeB+n];
        }
      
        int numDistinct(string S, string T) {
            // Start typing your C/C++ solution below
            // DO NOT write int main() function
            sizeA = S.size();
            sizeB = T.size();
           int *tp = new int[sizeA * sizeB] ;
           for(int i = 0; i< sizeA * sizeB ;i++)
               tp[i] = -1;
           
           return Dp(sizeA-1, sizeB-1,tp,S, T) ;
          
        }
    
     private :
        
        int sizeA;
        int sizeB;
    };

    上面必须先判断n == -1,在判断m == -1. 很重要。 

    一种写法:

    class Solution {
    public:
        int numDistinct(string S, string T) {
            // Note: The Solution object is instantiated only once and is reused by each test case.
         //if(S == null || T == null) return -1;
         int lens = S.size();
         int lent = T.size();
         
         if(lens == 0 || lent == 0) return 0;
         vector<vector<int>> m(lent+1,vector<int>(lens+1,0));
         for(int j = 0; j <= S.length(); j++) m[0][j] = 1;
        
         for(int i = 1; i <= lent; i++)
            for(int j = i; j <= lens; j++)
                m[i][j] = T[i-1] != S[j-1] ? m[i][j-1] : m[i-1][j-1] + m[i][j-1];
         
         return m[lent][lens]; 
        }
    };

    节省空间的写法:

    class Solution {
    public:
        int numDistinct(string S, string T) {
            // Note: The Solution object is instantiated only once and is reused by each test case.
        int M = T.length(); //subsequence length
        int N = S.length(); 
        if (M > N || M ==0 || N==0) {
            return 0;
        }
        vector<int> m(M, 0);    
        m[0] = (T[0] == S[0]?1:0);
        for (int i=1; i<N; ++i) {         
            for(int j=min(i,M); j>=1;--j) {
                m[j] = m[j] + ((S[i]==T[j])?m[j-1]:0);
            }
            m[0] = m[0] + (S[i]==T[0]?1:0);
        }        
        return m[M-1];
        }
    };
  • 相关阅读:
    poj 1035 字符串匹配
    拓扑排序的小总结
    POJ1018
    POJ1328详细题解
    POJ1159题解报告
    POJ1088 (滑雪)
    树状树组区间修改,单点修改模板
    spfa模板
    树状树组离散化求逆序对模板
    POJ3723(最小生成树,负权)
  • 原文地址:https://www.cnblogs.com/graph/p/3192357.html
Copyright © 2020-2023  润新知