题目描述
一个只包含'A'、'B'和'C'的字符串,如果存在某一段长度为3的连续子串中恰好'A'、'B'和'C'各有一个,那么这个字符串就是纯净的,否则这个字符串就是暗黑的。例如:
BAACAACCBAAA 连续子串"CBA"中包含了'A','B','C'各一个,所以是纯净的字符串
AABBCCAABB 不存在一个长度为3的连续子串包含'A','B','C',所以是暗黑的字符串
BAACAACCBAAA 连续子串"CBA"中包含了'A','B','C'各一个,所以是纯净的字符串
AABBCCAABB 不存在一个长度为3的连续子串包含'A','B','C',所以是暗黑的字符串
你的任务就是计算出长度为n的字符串(只包含'A'、'B'和'C'),有多少个是暗黑的字符串。
本题思路:
本题是典型的动态规划的问题,求f(n)与f(n-1)的关系的。
经发现,f(n)只与f(n-1)的最后两个字符有关,如果f(n-1)的最后两个字符相等,那么用输入ABC都可以得到f(n),如果f(n-1)的最后两个字符不等,那么只能输入和这两个字符一样的字符,比如AB我就只能在最后输入A或者B。
所以设f(n-1)由两部分组成,一部分是s(n-1),表示最后两个字符相等的所有集合的个数,一部分是d(n-1),表示最后两个字符不相等的所有集合的个数。
所以f(n)=3S(n-1)+2D(n-1)=2f(n)+S(n-1)
又由s(n-1)和d(n-1)推导s(n)和d(n),发现s(n-1)推导后的结果有1/3的结果是最后两个字符串相同的,比如AA有AAA,AAB,AAC;而d(n-1)推导后的结果有1/2的结果是最后两个字符串相同的,比如AB有ABA,ABB。
所以得到s(n)=s(n-1)+d(n-1)=f(n-1)
所以f(n)=2*f(n-1)+f(n-2)
代码如下:
<?php
$handler = fopen('php://stdin', 'r');
$n = trim(fgets($handler));
echo cal($n);
function cal($n) {
//动态规划
if ($n == 1) return 3;
if ($n == 2) return 9;
$res = 2*cal($n-1) + cal($n-2);
return $res;
}