Prolog用2个单词找到相似的字母

时间:2014-03-28 10:46:04

标签: prolog

我有这样的问题,我需要找到最长的单词,包含2个单词的字母,这些单词必须与原始单词的顺序相同,例如xabredpppaed必须返回{ {1}}。我不知道如何在Prolog

中这样做

3 个答案:

答案 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.