Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/algorithm/12.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Algorithm 计算形成字符串连续子串的有序且可能不连续的子串的数量_Algorithm_Dynamic Programming - Fatal编程技术网

Algorithm 计算形成字符串连续子串的有序且可能不连续的子串的数量

Algorithm 计算形成字符串连续子串的有序且可能不连续的子串的数量,algorithm,dynamic-programming,Algorithm,Dynamic Programming,假设S(N)是长度为N的字符串“012…”,其中“012”重复,直到有N个字符 对于任意给定的N,通过按顺序从字符串中选择可能不连续的字母,计算形成连续子字符串的方式的数量 例如,对于N=5,我们有S(N)=“01201” 连续子字符串和计数: '0', 2 '1', 2 '2', 1 '01', 3 (the two consecutive '01' along with the first and last character of '01201'). '12', 1 '20', 1 '01

假设S(N)是长度为N的字符串“012…”,其中“012”重复,直到有N个字符

对于任意给定的N,通过按顺序从字符串中选择可能不连续的字母,计算形成连续子字符串的方式的数量

例如,对于N=5,我们有S(N)=“01201”

连续子字符串和计数:

'0', 2
'1', 2
'2', 1
'01', 3 (the two consecutive '01' along with the first and last character of '01201').
'12', 1
'20', 1
'012', 1
'120', 1
'201', 1
'0120', 1
'1201', 1
'01201', 1

Total: 16
对于任意N,我们如何有效地计算它?我将发布我的最佳答案作为解决方案

请注意,这个问题最初来自Cococino223,但措词不当,在修复之前就被删除了。

假设f(n)是n的计数,f(n,k)是{0,1,2}中以k代表k结尾的子字符串中的n的计数

N  f(n, 0)  f(n, 1)  f(n, 2)  f(n)
0       0        0        0     0      
1       1        0        0     1      
2       1        2        0     3      
3       1        2        3     6      
4       5        2        3    10       
5       5        8        3    16       
6       5        8       12    25        
7      18        8       12    38        
8      18       27       12    57          
9      18       27       40    85          
10     59       27       40    126           
11     59       87       40    186
方法:f(n,k)只有在第n个字符串以k结尾时才改变。在这种情况下:

f(n, k) = f(n-1, k) + f(n-1, k') + 1
Where k' is the predecessor of k in '012' with wraparound.

E.g., f(6,2) = 12 = f(5,2) + f(5,1) + 1
这里的直觉是,我们有所有以k结尾的方式,它们不使用最新的字母(f(n-1,k)),所有使用最新的k的方式,它们必须等于在序列中使用前一个字母的所有方式,在末尾加上k(f(n-1,k'),再加上一个新的k(+1)

这是线性时间,恒定的记忆

--更新——如果你读到了变化的数字:1,2,3,5,8,12,18,27,40,59,87,128,188,276,405,594,871,这是

--更新--

调用M上面的平方矩阵,然后我们可以用M来计算k的连续值。例如,[12,18,27,1]*M=[18,27,40,1]

我们可以通过反复平方矩阵,在对数时间内用它来求解f(n)

E.g. M^8 = [4,   6,  9, 0]
           [3,   4,  6, 0]
           [6,   9, 13, 0]
           [12, 18, 27, 1]

[0, 0, 0, 1] * M^8 = [12, 18, 27, 1]
12 + 18 + 27 = 57 = f(8)
f(n)是M^n最下面一行的前三个元素之和


所以f(n)可以在对数时间内计算,但因为矩阵mult相当昂贵,这只对相对较大的n有意义。请注意,这适用于不是2的幂的数字,方法是将适当的2的幂的矩阵相乘。例如,13=1101,所以我们乘(M^1)(M^4)(M^8)。

我想知道重复的矩阵平方法是否可以将其降到对数时间(类似于斐波那契)。
E.g. M^8 = [4,   6,  9, 0]
           [3,   4,  6, 0]
           [6,   9, 13, 0]
           [12, 18, 27, 1]

[0, 0, 0, 1] * M^8 = [12, 18, 27, 1]
12 + 18 + 27 = 57 = f(8)