[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.

先想了一个回溯法,依次查找T中的串,并记录下标。

查找完成一遍,从T的最后一个字符再继续向后寻找,找不到就再找前一个   ,即rabbit  查找完一遍, 再继续找t ,没有再找i ,直到 r 找不到为止。

class Solution {
public:
    int numDistinct(string S, string T) {
        // Start typing your C/C++ solution below
        // DO NOT write int main() function
		int len_s = S.size();
		int len_t = T.size();
		if(len_t > len_s)
			return 0;
		vector <int>  pos(len_t,-1);
		int ret = 0;
		int i = 0;
		while(1){	
			while( i < len_t )
			{		
					if( i==0 ){
						pos[0] = S.find(T[i],pos[0]+1);
						if(pos[0]==string::npos)
							break; //exit flag
						else
							i++;
					}else{
						pos[i] = max(pos[i],pos[i-1]);
						pos[i] = S.find(T[i],pos[i]+1);
						if(pos[i]==string::npos)	
							i--; //backtrace
						else
							i++; 
					}
			}
			if(i == len_t)
			{
				ret ++;
				i = len_t -1; // used for next
			}else{
				break;
			}			
		}
		return ret;
    }
};

大数据通过,大数据没过。

又写了一个递归的

class Solution {
public:
    int help(string &S,int a,string &T,int c)
    {
    	if(a >= S.size())
			return 0;
		if(c >= T.size())
			return 0;
		int ret = 0;
		while(1)
		{
			int pos = S.find(T[c],a);
			if(pos == string::npos){
				return ret;
				}
			else{
                if(c+1 != T.size())
				    ret += help(S,pos+1, T,c+1);
                else
                    ret +=1;
				a = pos + 1;
			}
		}
	}
    int numDistinct(string S, string T) {
        // Start typing your C/C++ solution below
        // DO NOT write int main() function
		int len_s = S.size();
		int len_t = T.size();
		if(len_s < len_t)
			return 0;
		int ret = help(S,0,T,0);
		return ret;
    }
};

还是不行,坑爹了,DP吧,想了一下没想出来,觉得前面这个find 非常的坑。

找了一下网上的,UVA的题目和这个一样,貌似那个串更长,还要做一个大数类。

看了一下状态方程 如下:

dp[i][j]表示:b的前j个字符在a的前i个字符中出现的次数。

如果a[i] == b[j]则 dp[i][j] = dp[i-1][j] + dp[i-1][j-1]

如果a[i] != b[j]则 dp[i][j] = dp[i-1][j]

自己简单码了一下:

class Solution {
public:

    int numDistinct(string S, string T) {
        // Start typing your C/C++ solution below
        // DO NOT write int main() function
    	int len_s = S.size();
		int len_t = T.size();
		vector <vector <int> > f(len_s+1,vector<int>(len_t+1));
		if(len_s < len_t)
			return 0;
		for(int i = 0 ; i <= len_s ; i++)
			f[i][0] = 0;
		for(int j = 0 ; j <= len_t ; j++)
			f[0][j] = 0;

		for(int i = 1 ; i <= len_s ;i++)
			if(S[i-1]==T[0])
				f[i][1] = f[i-1][1] + 1;
			else
				f[i][1] = f[i-1][1];			
		for(int i = 2;  i <= len_s ; i++)
			for(int j = 2; j <= len_t ; j++)
				if(S[i-1]==T[j-1])
					f[i][j] = f[i-1][j-1] + f[i-1][j];
				else
					f[i][j] = f[i-1][j];
		return f[len_s][len_t];
    }
};


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值