我正试图轻微扭曲地解决经典的交错问题。扭曲是第三个字符串可以是前两个字符串循环的交错。例如:假设str1 =“ABC”,Str2 =“ADC”。然后第三个字符串可以是“ABC”和“ADC”循环的交错。循环可以是(string)^ k的任何前缀,其中k是一些正int。所以A的循环将是ABCABCA,因为它是str1 ^ 2的前缀。
一个澄清的例子如下:
str1等于“ABC”
str2 =“ADC”
Str3 =“ABCADCABADCCA” - 查找str3是否是str1和str2的循环的交错。
“答案:是的,因为str3是循环的交错:ABCABCA是str1 ^ 3的前缀,循环ADCADC是str2的前缀。”
答案 0 :(得分:0)
作为一个起点,我建议以下算法是正确的,没有评论其运行时的最佳性:
(ABC)*(e|A|AB)
其中e
是接受空字符串的正则表达式。我们现在为您的交错语言构建一个NFA(称为N,用于"非确定性"),如下所示:
然后我认为N接受你的交错语言:接受通过这个NFA的路径对应于选择" L"或" R"对于每个角色以及通过L的接受路径,标记为" L"以及通过R接受标记为" R"。
的字符的路径为了好玩,我在Haskell中组合了一个非常小的实现这个想法,而没有花费大量时间进行优化或类似的事情。 (所以没有最小化DFA,或试图记住状态转换,或类似的东西。)它对你的例子是可行的,至少:
import Data.List
type Position a = ([a], [a])
type DFAState a = (Position a, Position a)
type NFAState a = [DFAState a]
initialize :: [a] -> [a] -> NFAState a
initialize xs ys = [(([], xs), ([], ys))]
stepPosition :: Eq a => a -> Position a -> [Position a]
stepPosition x ([], [] ) = []
stepPosition x (bs, [] ) = stepPosition x ([], reverse bs)
stepPosition x (bs, e:es) = [(e:bs, es) | e == x]
ordNub :: Ord a => [a] -> [a]
ordNub = concatMap (take 1) . group . sort
stepDFA :: Ord a => a -> DFAState a -> [DFAState a]
stepDFA x (l, r) = ordNub
$ [(l', r) | l' <- stepPosition x l]
++ [(l, r') | r' <- stepPosition x r]
stepNFA :: Ord a => a -> NFAState a -> NFAState a
stepNFA x ss = concatMap (stepDFA x) ss
evalNFA :: Ord a => [a] -> NFAState a -> Bool
evalNFA _ [] = False
evalNFA [] ss = True
evalNFA (c:cs) ss = evalNFA cs (stepNFA c ss)
top :: Ord a => [a] -> [a] -> [a] -> Bool
top ls rs cs = evalNFA cs (initialize ls rs)
以下是ghci中的一些示例运行:
*Main> :set +s
*Main> top "ABC" "ADC" "ABCADCABADCCA"
True
(0.00 secs, 0 bytes)
*Main> top "ABC" "ADC" "ABCADCABADCCADABCC"
True
(0.01 secs, 0 bytes)
*Main> top "ABC" "ADC" "ABCADCABADCCADADCC"
False
(0.00 secs, 0 bytes)