小明思考

Just a software engineer
posts - 124, comments - 36, trackbacks - 0, articles - 0
  BlogJava :: 首页 :: 新随笔 :: 联系 :: 聚合  :: 管理

子序列计数

Posted on 2013-04-26 23:33 小明 阅读(2017) 评论(1)  编辑  收藏 所属分类: 数据结构和算法
问题给定两个字符串S和T,计算S的子序列为T的个数。

这里的字符串的子序列指的是删除字符串的几个字符(也可以不删)而得到的新的字符串,但是不能改变字符的相对位置。

比如“ACE”是“ABCDE”的子序列,但是“AEC”就不是。

如果S=“rabbbit” T=“rabit”,有3种不同的子序列为T的构成方法,那么结果应该返回3。

分析:

解法一:递归
直觉的解法是使用递归,先在S中找到T的第一个字符,然后递归查找在剩余的S查找剩余的T(除去首字符)。
如果T的长度为1,只需要计算S中一共有几个T就可以了。
代码如下,非常简洁,但是效率不高:

public int numDistinct(String S, String T) {
        int ls = S.length();
        int lt = T.length();
        if(ls<lt){
            return 0;
        }
        
        char[] cs = S.toCharArray();
        char t0 = T.charAt(0);
        String T1 = T.substring(1);
        
        int result = 0;
        for(int i=0;i<ls;++i){
            if(cs[i]==t0){
                if(lt>1){
                    result += numDistinct(S.substring(i+1),T1);
                }
                else{
                    ++result;
                }
            }    
        }
        return result;
    }

解法二,
为了提高效率,很自然的想法是使用动态规划,记录中间状态,从而避免重复计数。

状态转移方程如下,计D(m,n)为S的子串(0..m)中子序列为T(0..n)的个数。

那么D(m,n) = D(m-1,n) if S(m)<>T(n)
                 = D(m-1,n)+D(m-1,n-1) if (S(m)=T(n) and n>0)
                 = D(m-1,n)+1 if(S(m)=T(0) and n=0)

代码如下:复杂度为O(mn) m,n为S和T的长度

public int numDistinct(String S, String T) {
        int ls = S.length();
        int lt = T.length();
        if(ls<lt){
            return 0;
        }
        
        int[][] memo = new int[ls][lt];
        char[] cs = S.toCharArray();
        char[] ct = T.toCharArray();
        
        memo[0] = new int[lt];
        memo[0][0]= (cs[0]==ct[0])?1:0;
        
        for(int i=1;i<ls;++i){
            int[] mprev = memo[i-1];
            int[] m = memo[i] = new int[lt];
            char s = cs[i];
            for(int j=0;j<lt;++j){
                char t = ct[j];
                m[j] = mprev[j];
                if(s==t){
                    m[j] += ((j==0)?1:mprev[j-1]);
                }
            }
        }
        return memo[ls-1][lt-1];
    }

评论

# re: 子序列计数  回复  更多评论   

2013-06-12 23:56 by 初学者:阿古

7.字符串String str = “ABCDEABCDABC”;定义一个方法query,8.该方法算出该字符串中每一个字符的个数,9.打印格式如:
A——3
B——3
C——3
D——2
E——1

只有注册用户登录后才能发表评论。


网站导航: