我有这样的问题,我需要找到最长的单词,包含2个单词的字母,这些单词必须与原始单词的顺序相同,例如xabred
和pppaed
必须返回{ {1}}。我不知道如何在Prolog
答案 0 :(得分:2)
如果我正确理解了这些要求,那么请求是针对一个谓词,它将(重述)在两个给定的字符串(实际上是原子)中找到最长的子字符串。如果有多个相同,最长的长度,那么所有都需要列出。这表示结果是一个或多个单词的列表。
这里有一个工作,但它似乎可能有点"笨重"并且效率低下,特别是如果你考虑很长的字符串:
% Give a list of the longest matching words (substrings)
matchwords(W1, W2, Results) :-
setof(R, matchw(W1, W2, R), RSet), % Collect all the matching substrings
% and their lengths
reverse(RSet, Set), % Order by longest first
highest(Set, Results). % keep only the highest ones
% match atom-string W1 and W2 yielding atom-string Result of length N
matchw(W1, W2, N-Result) :-
atom_chars(W1, A1),
atom_chars(W2, A2),
matchl(A1, A2, R),
length(R, N),
atom_chars(Result, R).
% find a matching sublist between the first two lists
matchl([H|T1], [H|T2], [H|T]) :-
matchl(T1, T2, T).
matchl([H1|T1], [H2|T2], R) :-
H1 \= H2,
( matchl(T1, [H2|T2], R) ; matchl([H1|T1], T2, R) ).
matchl([], _, []).
matchl([_|_], [], []).
% Keep the highest elements at the front of a list of N-W pairs
highest([_-W], [W]).
highest([N1-W1,N2-_|_], [W1]) :-
N1 > N2.
highest([N1-W1,N2-W2|T], [W1|WT]) :-
N1 = N2,
highest([N2-W2|T], WT).
几个例子:
| ?- matchwords(xabred, pppaed, Matches).
Matches = [aed] ? a
(2 ms) no
| ?- matchwords(abcdef, acbedf, Matches).
Matches = [acef,acdf,abef,abdf] ? a
no
归结为Longest Common Sequence Problem。上面的代码不会尝试实现本文中提供的命令性解决方案。
答案 1 :(得分:2)
让我们首先找到任何常见的字符子序列(我假设我们正在处理字符列表):
common(Xs, Ys, [C|Cs]) :-
append(_,[C|Xs1],Xs),
append(_,[C|Ys1],Ys),
common(Xs1, Ys1, Cs).
common(_, _, []).
这产生了回溯的所有解决方案:
?- common([a, b, c, d], [e, c, d, b], Cs).
Cs = [b]
Yes (0.00s cpu, solution 1, maybe more)
Cs = [c, d]
Yes (0.00s cpu, solution 2, maybe more)
Cs = [c]
Yes (0.00s cpu, solution 3, maybe more)
Cs = [d]
Yes (0.02s cpu, solution 4, maybe more)
Cs = []
Yes (0.03s cpu, solution 5)
您现在可以使用findall / 3或setof / 3收集所有解决方案,并过滤掉最长的解决方案。或者,以下显示如何修改代码,使其首先返回最长的解决方案:
ordered_common(Xs, Ys, Cs) :-
le_min_length(Xs, Ys, Cs),
common(Xs, Ys, Cs).
le_min_length([_|Xs], [_|Ys], [_|Zs]) :-
le_min_length(Xs, Ys, Zs).
le_min_length(_, _, []).
这样,一旦提供了您喜欢的解决方案,就可以进行搜索。
?- ordered_common([a, b, c, d], [e, c, d, b], Cs).
Cs = [c, d]
Yes (0.00s cpu, solution 1, maybe more)
答案 2 :(得分:1)
sl(A, B, C) :-
atom_chars(A, Alist),
atom_chars(B, Blist),
intersection(Alist, Blist, Clist),
atom_chars(C, Clist).
试运行:
?- sl(xabred, pppaed, X).
X = aed.