我想在Prolog中創建查找輸入列表中最長的子集。例如,您輸入的[3,1,2]列表,輸出爲[1,2],增長最長的子集Prolog
?- subset([3,1,2], X).
X = [1,2]
我有代碼顯示了這個列表的所有子集:
subset([],[]).
subset([_|X],Y):-subset(X,Y).
subset([A|X],[A|Y]):-subset(X,Y).
任何人都可以幫助我找到最長的增長子集?
我想在Prolog中創建查找輸入列表中最長的子集。例如,您輸入的[3,1,2]列表,輸出爲[1,2],增長最長的子集Prolog
?- subset([3,1,2], X).
X = [1,2]
我有代碼顯示了這個列表的所有子集:
subset([],[]).
subset([_|X],Y):-subset(X,Y).
subset([A|X],[A|Y]):-subset(X,Y).
任何人都可以幫助我找到最長的增長子集?
你的意思是[1,3,5,6,7]
是[4,1,3,8,9,5,6,7]
的答案嗎? IOW,你真的是指子集,還是僅僅是子列表,即列表中的連續部分?
如果是後者,您將不需要子集。搜索是線性的。如果在列表[a,b,c,d,e,f]
中發現d > e
和增加的序列[a,b,c,d]
停止,則不需要立即從b
重新開始搜索:序列仍將在d
處中斷。您將繼續從e
進行搜索。
因此,我們只是在搜索過程中攜帶一些附加信息,當前的和獲勝的子序列。和他們的長度。
longest_incr([],0-[]).
longest_incr([A|B],RL-R):- % R is the result, of length RL
longest_aux(B,[],0, [A],1, RL-R).
longest_aux([], Win,N, Curr,K, RL-R):-
(K>N -> RL=K, reverse(Curr,R) ; RL=N, reverse(Win,R)).
longest_aux([A|B],Win,N, Curr,K, RL-R):- Curr = [X|_], L is K,
(A>X -> longest_aux(B,Win, N, [A|Curr],L+1,RL-R) % keep adding
; L>N -> longest_aux(B,Curr,K, [A], 1, RL-R) % switch the winner
; longest_aux(B,Win, N, [A], 1, RL-R) % winner unbeaten
).
如果OTOH你真的需要最長的子集......那裏就有矛盾。一組可以有它的元素重新排列,所以給定的列表中最長的子集將是
longset_subset(L,R):- sort(L,S), R=S.
也許你指的是最長的保序子序列,即允許它是不連續的。然後你就可以收集到您的subset
所有解決方案findall
或類似的斷言,並分析這些結果:
longest_subseq(L,R):-
findall(S, subset(L,S), X),
maplist(longest_incr, X, Y),
keysort(Y, Z),
last(Z, _Len-R).
上面有很多在它的冗餘。我們可以嘗試通過只允許增加子序列,以提高其效率:
incr_subseq([],[]).
incr_subseq([_|X],Y):- incr_subseq(X,Y).
incr_subseq([A|X],[A|Y]):- incr_subseq(X,Y), (Y=[] ; Y=[B|_], A<B).
現在所有由上述謂詞中發現的子序列將越來越大,因此我們就可以把他們的length
S:
lenlist(List,Len-List) :- length(List,Len).
longest_subseq(L,R):-
findall(S, incr_subseq(L,S), X),
maplist(lenlist, X, Y),
keysort(Y, Z),
last(Z, _Len-R).
或者,線性搜索longest_incr
可以調整爲更有效的解決方案。它不會只維護一個獲勝的子序列,而是會沿着輸入列表保留所有相關的可能性。
只是出於好奇,那會是在序言中可以實現這樣的尋找最長遞增子:
如果有可能,我怎麼能做到這一點的Prolog的?
的列表'X',答案'R'將滿足'sort(X,R)'。因爲集合被認爲是平等的,不管它們的元素的順序是什麼。如果你的意思是*子序列*,即包含原始順序的元素和可能來自列表的非連續區域的元素,那麼這就是這個問題所要求的。 – 2013-04-06 11:46:23
我已經更新了我的答案。我調整了你的想法順便說一句 - 我測試的子序列的增加,因爲它們正在生成。 – 2013-04-07 16:34:21
我實際上假設他的意思是「最長的子序列」,基於他的「子集」。有很多這樣做的算法。在他的情況下,他可以簡單列舉所有增加的子序列(他稱之爲子集)並查看哪一個最長。 – 2013-03-27 11:16:14
@Boris你的意思是連續的,還是非連續的?基於他的「子集」,或許是第二種情況? – 2013-03-27 11:28:49
http://en.wikipedia.org/wiki/Longest_increasing_subsequence非連續的,每個定義。如果它是連續的,我會猜測它將被稱爲子串。然而順序很重要(因此順序)。有大量可用的算法。 – 2013-03-27 11:30:58