lintcode 734. Number of Subsequences of Form a^i b^j c^k

来源:互联网 发布:如何投诉淘宝售假 编辑:程序博客网 时间:2024/06/11 01:24

lintcode 734. Number of Subsequences of Form a^i b^j c^k

题目大意:
给一串由a b c组成的字符串,让你求可以找出多少个满足正则 ^ a+b+c+$的子序列(不是子串)。

题目思路:
首先的话肯定是可以递归暴力搜索的,然后就挂了,这是我暴力的代码:

    def countSubsequences(self, source):        # write your code here        def search(x):            for i in range(x+1, self.l):                if is_valid(x, i):                    search(i)        def is_valid(a, b):            if source[a] <= source[b] and ord(source[b]) - ord(source[a]) != 2:                if source[b] == 'c':                    self.result += 1                return True            return False        self.result = 0        while source[0:1] != 'a' and len(source) > 0:            source = source[1:]        while source[-1:] != 'c' and len(source) > 0:            source = source[0:-1]        self.l = len(source)        for i in range(0, self.l - 2):            if source[i] == 'a':                search(i)        return self.result

然后下面提供一个非暴力版本的算法,看了 kaaokou同学的博客 才想到(我好菜啊qwq
他博客里讲的可能比较简略点但大概意思传达到了这里写一下我自己的理解。首先要明确一个思路就是说比如当以字符‘c’结尾时有多少种情况是取决于这个c之前的以c结尾的组合数和以b结尾的组合数,当以b结尾时有多少种情况取决于这个b之前的以b结尾的组合数和以a结尾的组合数,当以a结尾时有多少种情况则仅仅取决于这个a之前的以a结尾的组合数,注意这里说以a结尾或者以b结尾的意思并不是真正的结尾,因为结尾一定要以c,这里结尾的意思就是判断到这一位的时候。
然后我们设以a结尾的组合数为Sa,以b结尾的组合数为Sb,以c结尾的组合数为Sc,那么这里就有三个层层递进的关系了:
1. Sa => Sa
2. Sa , Sb => Sb
3. Sb, Sc => Sc
我们最后要得到的答案其实就是Sc。
然后接下仔细分析下这三个关系式的具体实现:
1. Sa => Sa
假设一个a前面的以a结尾的组合数为x,那么又来了个a,这个x会变成多少?答案是2x+1,这个2x+1可以其实可以看成 x+x+1,第一份x就是原来的x,即无视掉这个新来的a,第二份x就是对原来的x个组合后面都加上这个新来的a,最后那个1就是忽略掉前面的a,只用新来的这个a,即字符串’a’。 当然这个2x+1也是可以严格计算出来的,假设新的a之前出现过n个字符a,那么x应该等于 2^n-1,那算是这个新来的a之后就出现了n+1个a,那组合数应该就等于 2^(n+1)-1。即x = 2^n-1,设ax+b = 2^(n+1)-1,就可以计算出a=2,b=1。
2. Sa, Sb => Sb
假设这时候来了个新的b,这个b前面以a结尾的组合数为Sa,以b结尾的组合数为Sb,那如何去更新Sb的值?很显然 Sb = Sa + 2 * Sb,我们可以再把这个分开来看成 Sb = Sa + Sb + Sb,第一份Sa就是在所有以a结尾的组合后面跟上这个新来的b,第二份Sb可以看成在 所有以b结尾的组合后面跟上这个b,第三份Sb可以看成直接取所有以b结尾的组合,把新的b不要了。
3. Sb, Sc => Sc
这个道理跟2一样,同理可得Sc = Sb + 2 * Sc
所以最后的代码如下:

    def countSubsequences(self, source):        # write your code here        a = 0        b = 0        c = 0        for i in range(0, len(source)):            if source[i] == 'a':                a = 2 * a + 1            elif source[i] == 'b':                b = a + 2 * b            elif source[i] == 'c':                c = b + c * 2        return c
原创粉丝点击