三字母字符串组合

来源:互联网 发布:视频拼接软件 编辑:程序博客网 时间:2024/04/30 12:26

本总结是是个人为防止遗忘而作,不得转载和商用。

题目

         仅由三个字符A、B、C构成字符串,且字符串任意三个相邻元素不能完全相同。如“ACCCAB”不合法,“ABBCBCA”合法。

         求满足条件的长度为n的字符串个数。

         PS1:假定不考虑整数溢出

         PS2:要求时间和空间复杂度不高于O(N)。

分析

         若当前已经有了所有长度为n-1的合法字符串,如何在末端增加一个字符,形成长度为n的字符串呢?

         为了解决此问题就需要将长度为n-1字符串分成“末尾两个字符不相等”和“末尾两个字符相等”两种情况,各自数目记做dp[n-1][0], dp[n-1][1],即:

                   dp[n][0]:长度为n的字符串最后两个不相同

                  dp[n][1]:长度为n的字符串最后两个相同

         然后分别考虑这两种情况。

         1,要想使“长度为n的字符串最后两个不相同”,则“长度为n-1的字符串的最后两个字符可以相等,可以不相等,且相等有两种情况,不相等有两种情况”,如:

                   下面的红色字母是第n位

                   n-1的字符串的最后两个字符相等时,长度为n的字符串最后两个不相同:

                            情况1:ABCAABABBC

                            情况2:ABCAABABBA

                   n-1的字符串的最后两个字符不相等时,长度为n的字符串最后两个不相同:

                            情况1:ABCAABABAC

                            情况2:ABCAABABAB

         所以dp[n][0] = 2*dp[n-1][0] + 2*dp[n-1][1]。

         2,要想使“长度为n的字符串最后两个相同”,则“长度为n-1的字符串的最后两个字符只能不相等,且只有一种情况”,如:

                   下面的红色字母是第n位

                   情况1:ABCAABABAA

         所以dp[n][1] = dp[n-1][0]

        

         最后,初始条件是:

                   dp[1][0]= 3

                   dp[1][1]= 0

状态转移方程

         现在就可以写出状态转移方程了,如下:

                   初始条件:

                            dp[1][0] = 3

                           dp[1][1]= 0

                   状态转移方程:

                            dp[n][0] = 2*dp[n-1][0] +2*dp[n-1][1]

                           dp[n][1]= dp[n-1][0]

滚动数组

         按理说有了初始条件和状态转移方程就可以写代码了,不过可以在优化优化。

         因为有了长度n-1的字符串的数量就可以计算长度为n的,有了长度为n的就可以计算长度为n+1的,所以没必要将n-1的所有情况都保存,只需要记录当前的就OK了。

         所以状态转移方程可以更新成“滚动数组”的样子,如下。

                   dp[0]= 2*dp[0] + 2*dp[1]

                   dp[1]= dp[0]

         PS:使用滚动数组,将空间复杂度由O(N)降到O(1)

代码

         于是代码就好简单好简单,如下:

int CalcCount(int n){     // 初始条件   int nNonRepeat = 3   int nRepeat = 0;    // 滚动数组   int t;   for (int i = 2; i <= n; i++) {       t = nNonRepeat;       nNonRepeat = 2*(nNonRepeat + nRepeat);       nRepeat = t;   }      return nRepeat + nNonRepeat;}



不过还可以再优化!

         你看,对于滚动数组,如果把dp[0]看成x,dp[1]看成y的话,那这个式子就可以写出下面的样子:

                   x= 2x + 2y

                   y= x

         如果用矩阵表达的话就是:

                    

         即:我们就是在求(x,y)这么一个向量在矩阵的作用下不停的迭代的过程,即:

         而这里最后需要计算一个n-1次幂,这就可以使用http://blog.csdn.net/xueyingxue001/article/details/52913274中介绍的方法,这样一来就可以将时间复杂度降为了O(logN)

0 0
原创粉丝点击