erl_string-字符串匹配的KMP算法

来源:互联网 发布:哪家运营商4g网络最好 编辑:程序博客网 时间:2024/06/03 00:35

字符串匹配是计算机的基本任务之一。
  许多算法可以完成这个任务,Knuth-Morris-Pratt算法(简称KMP)是最常用的之一。它以三个发明者命名,起头的那个K就是著名科学家Donald Knuth。
kmp算法文字描述,说明请到http://kb.cnblogs.com/page/176818/ 博客看,里面说的比较详细这里就不再赘述。
下面直接上代码:

%%字符串匹配的KMP算法%%移动位数 = 已匹配的字符数 - 对应的部分匹配值%%return pos 匹配的头字母位置 前一位kmp_match(Word,CWord,Pos)-> MatchTableL = match_table_key(Word,[],[]), kmp_match0(Word,CWord,Pos,MatchTableL).kmp_match0(_,[],Pos,_MatchTableL)-> Pos;kmp_match0(Word,CWord,Pos,MatchTableL)-> case kmp_match1(Word,CWord,[],Pos,MatchTableL) of  false->   kmp_match0(Word,[],0,MatchTableL);  {MvPos,false}->   {_,NCWord} = lists:split(MvPos,CWord),   case NCWord of    []->     0;    _->     kmp_match0(Word,NCWord,Pos+MvPos,MatchTableL)   end;  {FPos,true}->   kmp_match0(Word,[],FPos,MatchTableL) end.kmp_match1(_,[],[],_,_)-> false;kmp_match1([],_,_,Pos,_)-> {Pos,true};kmp_match1([HW|TW],[HCW|TCW],MatchList,Pos,MatchTableL) when HW == HCW -> kmp_match1(TW,TCW,MatchList ++ [HW],Pos,MatchTableL);kmp_match1([HW|_TW],[HCW|_TCW],[],_,_) when HW =/= HCW -> {1,false};kmp_match1([HW|_TW], [HCW|_TCW], MatchList, _Pos,MatchTableL) when HW =/= HCW andalso MatchList =/= [] -> MatchLen = length(MatchList), {TTT,Key} = lists:nth(MatchLen,MatchTableL), MvPos = MatchLen - Key, {MvPos,false}.%%部分匹配值%%   "部分匹配值"就是"前缀"和"后缀"的最长的共有元素的长度。以"ABCDABD"为例,%%   - "A"的前缀和后缀都为空集,共有元素的长度为0%%   - "AB"的前缀为[A],后缀为[B],共有元素的长度为0;%%   - "ABC"的前缀为[A, AB],后缀为[BC, C],共有元素的长度0%%   - "ABCD"的前缀为[A, AB, ABC],后缀为[BCD, CD, D],共有元素的长度为0;%%   - "ABCDA"的前缀为[A, AB, ABC, ABCD],后缀为[BCDA, CDA, DA, A],共有元素为"A",长度为1%%   - "ABCDAB"的前缀为[A, AB, ABC, ABCD, ABCDA],后缀为[BCDAB, CDAB, DAB, AB, B],共有元素为"AB",长度为2;%%   - "ABCDABD"的前缀为[A, AB, ABC, ABCD, ABCDA, ABCDAB],后缀为[BCDABD, CDABD, DABD, ABD, BD, D],共有元素的长度为0%% [{A,0},{B,0},{C,0},{D,0},{A,1},{B,1},{D,0}]%% match_table_key("ABCDABD",[],[])match_table_key([],FList,_)-> FList;match_table_key([H|Tail],FList,HL)-> Num = check_same_len(HL++[H]), match_table_key(Tail,FList++[{H,Num}],HL++[H]).check_same_len(L) when length(L) =< 1 -> 0;check_same_len(L) -> Len = length(L), {_,HIlist,_} =  lists:foldl(fun(K,{HA,Acc,C})->   if C < Len ->    {HA++[K],[HA++[K]|Acc],C+1};    true->     {HA,Acc,C+1}   end  end,{[],[],1},L), {_,TIlist,_} =  lists:foldr(fun(K1,{TA,Acc1,C1})->   if C1 < Len ->    {[K1]++TA,[[K1]++TA|Acc1],C1+1};    true->     {TA,Acc1,C1+1}   end  end,{[],[],1},L), lists:foldl(fun(K,Acc3)->  TLen = length(K),  case lists:member(K,TIlist) andalso TLen > Acc3 of   true->    TLen;   _->    Acc3  end end,0,HIlist).
0 0
原创粉丝点击