我正在寻找一种算法来解决以下问题:
鉴于序列n
包含从0
到9
和m
其他序列的数字,找到等于的最小序列(包含最低量)序列n
。
示例
n = 123456
m1 = 12
m2 = 34
m3 = 56
m4 = 3456
output = m1 + m4 = 123456
到目前为止我想到的事情
使用FSM或特里树查找开头最长序列的基本贪婪技术:
while n not null
longest = the longest sequence fitting in the beginning of n
print longest
n = n - longest
反例
n = 123456
m1 = 12
m2 = 1
m3 = 23456
m4 = 3
m5 = 4
m6 = 5
m7 = 6
algorithm will find m1 + m4 + m5 + m6 + m7 (12 + 3 + 4 + 5 + 6)
algorithm should find m2 + m3 (1 + 23456)
另一种贪婪的方法
array = {n} #this represents words to be matched
while array not empty
(word, index) = find longest sequence covering part of any word in array and its index
split array[index] into two words - first before found word, second after it
if any of those split items is null
remove it
反例
n = 12345678
m1 = 3456
m2 = 1
m3 = 2
m4 = 7
m5 = 8
m6 = 123
m7 = 45
m8 = 678
algorithm will find m2 + m3 + m1 + m4 + m5 (1 + 2 + 3456 + 7 + 8)
algorithm should find m6 + m7 + m8 (123 + 45 + 678)
答案 0 :(得分:2)
您可以使用动态编程逐步计算结果。
让我们定义s(i)生成n的第一个字符的最短序列。
对于最后一个例子的数据,s(i)的值是:
s(0) = { }
s(1) = { m2 }
s(2) = { m2 + m3 }
s(3) = { m6 }
s(4) = { } (no sequence can generate "1234")
s(5) = { m6 + m7 }
s(6) = { m2 + m3 + m1 }
s(7) = { m2 + m3 + m1 + m4 }
s(8) = { m6 + m7 + m8 }
您必须按顺序计算s(1)
到s(n)
。在每个步骤i
,您会查看从s(0)
到s(i-1)
的所有序列,并保持最短。
例如,对于s(8)
,您会发现有两种解决方案:
s(8) = s(5) + m8
s(8) = s(7) + m5
你保持最短。
算法:
function computeBestSequence(word, list of subsequences m)
let s(0) := {}
for i from 1 to n // We will compute s(i)
let minSize := +inf.
for j from 0 to i - 1
for all sequences mx from m1 to m9
if s(j) + mx = the first i char of word
if size of s(j) + mx is less than minSize
minSize := size of s(j) + mx
s(i) := s(j) + mx
编辑:
算法可以简化为仅使用两个循环:
let s(0) := {}
for i from 1 to n // We will compute s(i)
let minSize := +inf.
for all sequences mx from m1 to m9
let j := i - mx.length
if s(j) + mx = the first i char of word
if size of s(j) + mx is less than minSize
minSize := size of s(j) + mx
s(i) := s(j) + mx
答案 1 :(得分:0)
Based on obourgains answer java code of his edit version:
extern crate chrono;
use chrono::prelude::*;
fn main() {
let dt1 = NaiveDateTime::parse_from_str(
"2017-08-30 18:34:06.638997932 UTC",
"%Y-%m-%d %H:%M:%S%.9f UTC"
);
println!("{:?}", dt1); // Ok(2017-08-30T18:34:06.638997932)
}
The test:
_CSRUN_STATE_DIRECTORY
The output:
c:\AzureTemp