Distinct Subsequences
2016-06-24 14:12
435 查看
题目描述:
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,
Here is an example:
S =
Return
这个题首先想到的dfs,然后写了下面的代码。想都不想就超时了:
public class Solution {
public int numDistinct(String s, String t) {
return getNumDistinct(s, 0, t, 0);
}
public int getNumDistinct(String s, int sStart, String t, int tStart){
if(s.length()-sStart<t.length()-tStart){
return 0;
}
if(tStart==t.length()) return 1;
if(sStart==s.length()){
return 0;
}
if(s.charAt(sStart)!=t.charAt(tStart)){
return getNumDistinct(s, sStart+1, t, tStart);
}else{
return getNumDistinct(s, sStart+1, t, tStart+1)+getNumDistinct(s, sStart+1, t, tStart);
}
}
}
然后就是在这里加入备忘录,用dp记录下s[sStart, s.length-1]中包含t[tStart, t.length-1]的子串数。
时间性能增强很多,但是会出现这个错误:Line 32: java.lang.StackOverflowError。内存溢出,也就是递归调用次数多了。还是得转换成自下而上的dp算法才行!
public class Solution {
public int numDistinct(String s, String t) {
int slen=s.length(),tlen=t.length();
int[][] dp=new int[slen+1][tlen+1];
for(int i=0;i<=slen;i++){
for(int j=0;j<=tlen;j++){
dp[i][j]=Integer.MAX_VALUE;
}
}
int num= getNumDistinct(s, 0, t, 0, dp);
return num;
}
public int getNumDistinct(String s, int sStart, String t, int tStart, int[][] dp){
if(s.length()-sStart<t.length()-tStart){
dp[sStart][tStart]=0;
return 0;
}
if(tStart==t.length()){
dp[sStart][tStart]=1;
return 1;
}
if(sStart==s.length()){
dp[sStart][tStart]=0;
return 0;
}
if(s.charAt(sStart)!=t.charAt(tStart)){
if(dp[sStart+1][tStart]!=Integer.MAX_VALUE){
dp[sStart][tStart]=dp[sStart+1][tStart];
return dp[sStart+1][tStart];
}else{
int a = getNumDistinct(s, sStart+1, t, tStart, dp);
dp[sStart][tStart]=a;
return a;
}
}else{
int dp1=0,dp2=0;
if(dp[sStart+1][tStart+1]!=Integer.MAX_VALUE){
dp1=dp[sStart+1][tStart+1];
}else{
dp1=getNumDistinct(s, sStart+1, t, tStart+1, dp);
}
if(dp[sStart+1][tStart]!=Integer.MAX_VALUE){
dp2=dp[sStart+1][tStart];
}else{
dp2=getNumDistinct(s, sStart+1, t, tStart, dp);
}
dp[sStart][tStart]=dp1+dp2;
return dp1+dp2;
}
}
} AC代码如下:
动态规划,定义dp[i][j]为字符串i变换到j的变换方法。
如果S[i]==T[j],那么dp[i][j] = dp[i-1][j-1] + dp[i-1][j]。意思是:如果当前S[i]==T[j],那么当前这个字母即可以保留也可以抛弃,所以变换方法等于保留这个字母的变换方法加上不用这个字母的变换方法。
如果S[i]!=T[i],那么dp[i][j] = dp[i-1][j],意思是如果当前字符不等,那么就只能抛弃当前这个字符。
递归公式中用到的dp[0][0] = 1,dp[i][0] = 0(把任意一个字符串变换为一个空串只有一个方法)
public class Solution {
public int numDistinct(String S, String T) {
if(S==null||T==null) {
return 0;
}
if(S.length()<T.length()) {
return 0;
}
int [][] dp = new int[S.length()+1][T.length()+1];
dp[0][0] = 1;
for(int i=0;i<S.length();i++) {
dp[i][0] = 1;
}
for(int i=1;i<=S.length();i++) {
for(int j=1;j<=T.length();j++) {
dp[i][j] = dp[i-1][j];
if(S.charAt(i-1)==T.charAt(j-1)) {
dp[i][j] += dp[i-1][j-1];
}
}
}
return dp[S.length()][T.length()];
}
}
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.
这个题首先想到的dfs,然后写了下面的代码。想都不想就超时了:
public class Solution {
public int numDistinct(String s, String t) {
return getNumDistinct(s, 0, t, 0);
}
public int getNumDistinct(String s, int sStart, String t, int tStart){
if(s.length()-sStart<t.length()-tStart){
return 0;
}
if(tStart==t.length()) return 1;
if(sStart==s.length()){
return 0;
}
if(s.charAt(sStart)!=t.charAt(tStart)){
return getNumDistinct(s, sStart+1, t, tStart);
}else{
return getNumDistinct(s, sStart+1, t, tStart+1)+getNumDistinct(s, sStart+1, t, tStart);
}
}
}
然后就是在这里加入备忘录,用dp记录下s[sStart, s.length-1]中包含t[tStart, t.length-1]的子串数。
时间性能增强很多,但是会出现这个错误:Line 32: java.lang.StackOverflowError。内存溢出,也就是递归调用次数多了。还是得转换成自下而上的dp算法才行!
public class Solution {
public int numDistinct(String s, String t) {
int slen=s.length(),tlen=t.length();
int[][] dp=new int[slen+1][tlen+1];
for(int i=0;i<=slen;i++){
for(int j=0;j<=tlen;j++){
dp[i][j]=Integer.MAX_VALUE;
}
}
int num= getNumDistinct(s, 0, t, 0, dp);
return num;
}
public int getNumDistinct(String s, int sStart, String t, int tStart, int[][] dp){
if(s.length()-sStart<t.length()-tStart){
dp[sStart][tStart]=0;
return 0;
}
if(tStart==t.length()){
dp[sStart][tStart]=1;
return 1;
}
if(sStart==s.length()){
dp[sStart][tStart]=0;
return 0;
}
if(s.charAt(sStart)!=t.charAt(tStart)){
if(dp[sStart+1][tStart]!=Integer.MAX_VALUE){
dp[sStart][tStart]=dp[sStart+1][tStart];
return dp[sStart+1][tStart];
}else{
int a = getNumDistinct(s, sStart+1, t, tStart, dp);
dp[sStart][tStart]=a;
return a;
}
}else{
int dp1=0,dp2=0;
if(dp[sStart+1][tStart+1]!=Integer.MAX_VALUE){
dp1=dp[sStart+1][tStart+1];
}else{
dp1=getNumDistinct(s, sStart+1, t, tStart+1, dp);
}
if(dp[sStart+1][tStart]!=Integer.MAX_VALUE){
dp2=dp[sStart+1][tStart];
}else{
dp2=getNumDistinct(s, sStart+1, t, tStart, dp);
}
dp[sStart][tStart]=dp1+dp2;
return dp1+dp2;
}
}
} AC代码如下:
动态规划,定义dp[i][j]为字符串i变换到j的变换方法。
如果S[i]==T[j],那么dp[i][j] = dp[i-1][j-1] + dp[i-1][j]。意思是:如果当前S[i]==T[j],那么当前这个字母即可以保留也可以抛弃,所以变换方法等于保留这个字母的变换方法加上不用这个字母的变换方法。
如果S[i]!=T[i],那么dp[i][j] = dp[i-1][j],意思是如果当前字符不等,那么就只能抛弃当前这个字符。
递归公式中用到的dp[0][0] = 1,dp[i][0] = 0(把任意一个字符串变换为一个空串只有一个方法)
public class Solution {
public int numDistinct(String S, String T) {
if(S==null||T==null) {
return 0;
}
if(S.length()<T.length()) {
return 0;
}
int [][] dp = new int[S.length()+1][T.length()+1];
dp[0][0] = 1;
for(int i=0;i<S.length();i++) {
dp[i][0] = 1;
}
for(int i=1;i<=S.length();i++) {
for(int j=1;j<=T.length();j++) {
dp[i][j] = dp[i-1][j];
if(S.charAt(i-1)==T.charAt(j-1)) {
dp[i][j] += dp[i-1][j-1];
}
}
}
return dp[S.length()][T.length()];
}
}
相关文章推荐
- [LeetCode] Longest Consecutive Sequence
- ssm框架搭建+easyui增删改查实现
- 357. Count Numbers with Unique Digits
- Vue学习3--数据绑定语法
- iOS通知 you still need to add "remote-notification" to the list of your supported UIBackgroundModes
- 框架: require.js
- easyui dialog 关闭按钮怎么去掉
- vuejs和webpack项目(VueComponent)初尝试——瀑布流组件
- 【Arduino官方教程】基础示例(六):读取模拟电压
- User Domain\User does not have required permissions
- UITableViewCell刚出现时,出现的动画
- easyui + jdbc 实现简单的数据库管理。
- Gradle详解-Chapter 20. The Build Lifecycle
- 改变UINavigationBar导航条标题颜色和字体
- ueditor 编辑器的配置 实现上传图片---附效果图
- stack&queue
- FreeSWITCH安装报错“You must install libyuv-dev to build mod_fsv”的解决方案
- Hbuilder中百度地图插件的使用
- 富文本ueditor使用记录
- Specified RequestProcessor not compatible with TilesRequestProcessor