获得ERLANG中最长的共同后续序列

Thi*_*Guy 3 string erlang function lcs

我是ERLANG的新手,我知道基础知识.这就像计划,但更广泛.我知道如何创建一个函数但是我在创建一个获得最长公共子序列的函数时遇到了问题.

lcs(str1,str2) 是一个接受两个字符串并输出整数的函数:

lcs(algorithm,logarithm)将输出7因为可以做出最长公共子序列lgrithm,其是7在大小.

任何答案都非常感谢.

Pie*_*rre 5

Rosettacode上有一个很好的LCS算法实现,它是:

-module(lcs).
-compile(export_all).

lcs_length(S,T) ->
    {L,_C} = lcs_length(S,T,dict:new()),
    L.

lcs_length([]=S,T,Cache) ->
    {0,dict:store({S,T},0,Cache)};
lcs_length(S,[]=T,Cache) ->
    {0,dict:store({S,T},0,Cache)};
lcs_length([H|ST]=S,[H|TT]=T,Cache) ->
    {L,C} = lcs_length(ST,TT,Cache),
    {L+1,dict:store({S,T},L+1,C)};
lcs_length([_SH|ST]=S,[_TH|TT]=T,Cache) ->
    case dict:is_key({S,T},Cache) of
        true -> {dict:fetch({S,T},Cache),Cache};
        false ->
            {L1,C1} = lcs_length(S,TT,Cache),
            {L2,C2} = lcs_length(ST,T,C1),
            L = lists:max([L1,L2]),
            {L,dict:store({S,T},L,C2)}
    end.

lcs(S,T) ->
    {_,C} = lcs_length(S,T,dict:new()),
    lcs(S,T,C,[]).

lcs([],_,_,Acc) ->
    lists:reverse(Acc);
lcs(_,[],_,Acc) ->
    lists:reverse(Acc);
lcs([H|ST],[H|TT],Cache,Acc) ->
    lcs(ST,TT,Cache,[H|Acc]);
lcs([_SH|ST]=S,[_TH|TT]=T,Cache,Acc) ->
    case dict:fetch({S,TT},Cache) > dict:fetch({ST,T},Cache) of
        true ->
            lcs(S,TT,Cache, Acc);
        false ->
            lcs(ST,T,Cache,Acc)
    end.
Run Code Online (Sandbox Code Playgroud)

用作:

raringbeast:Code pierre $ erl
Erlang R15B01 (erts-5.9.1) [source] [64-bit] [smp:8:8] [async-threads:0] [hipe]
[kernel-poll:false]

Eshell V5.9.1  (abort with ^G)
1> c(lcs).
{ok,lcs}
2> lcs:lcs("logarithm", "algorithm").
"lgrithm"
3> lcs:lcs_length("logarithm", "algorithm").
7
Run Code Online (Sandbox Code Playgroud)

-

编辑:使算法更容易理解

这里的缓存只是一种在某些情况下提高算法性能的有趣方法,但这不是必需的.我们可以写,删除缓存:

lcs_length([],_T) ->
    0;
lcs_length(_S,[]) ->
    0;
lcs_length([_H|ST],[_H|TT]) ->
    1 + lcs_length(ST,TT);
lcs_length([_SH|ST]=S,[_TH|TT]=T) ->
    L1 = lcs_length(S,TT),
    L2 = lcs_length(ST,T),
    lists:max([L1,L2]). 
Run Code Online (Sandbox Code Playgroud)

总结一下:

  1. LCS的""和任何东西都是0.
  2. 任何事物和""的LCS都是一样的.
  3. 由相同字母开头的两个单词的LCS是两个单词的LCS减去第一个字母加1.
  4. 以不同字母开头的两个单词的LCS是(a)第一个单词的LCS减去第一个字母和第二个单词的最大值,以及(b)第一个单词的LCS和第二个单词的减去第一个字母的最大值.