检查字符串是否是Prolog中的子字符串

时间:2013-11-27 18:40:20

标签: prolog substring dcg subsequence

有没有办法检查字符串是否是Prolog中另一个字符串的子字符串?我尝试将字符串转换为字符列表,然后检查第一个集合是否是第二个集合的子集,这似乎不够限制。这是我目前的代码:

isSubstring(X,Y):-
        stringToLower(X,XLower),
        stringToLower(Y,YLower),
        isSubset(XLower,YLower).

isSubset([],_).
isSubset([H|T],Y):-
        member(H,Y),
        select(H,Y,Z),
        isSubset(T,Z).

stringToLower([],[]).
stringToLower([Char1|Rest1],[Char2|Rest2]):-
        char_type(Char2,to_lower(Char1)),
        stringToLower(Rest1,Rest2).

如果我用

进行测试
  

于issubstring( “测试”, “tesZting”)。

它返回yes,但是应该返回no。

4 个答案:

答案 0 :(得分:5)

目前尚不清楚字符串是什么意思。但既然你说你把它转换成一个列表,你可能意味着原子。 ISO Prolog为此目的提供atom_concat/3sub_atom/5

| ?- atom_concat(X,Y,'abc').
  X = '', Y = abc
; X = a, Y = bc
; X = ab, Y = c
; X = abc, Y = ''.

| ?- sub_atom('abcbcbe',Before,Length,After,'bcb').
  Before = 1, Length = 3, After = 3
; Before = 3, Length = 3, After = 1.

否则,请使用DCG!这是

的方式
seq([]) --> [].
seq([E|Es]) --> [E], seq(Es).

... --> [] | [_], ... .

subseq([]) --> [].
subseq(Es) --> [_], subseq(Es).
subseq([E|Es]) --> [E], subseq(Es).

seq_substring(S, Sub) :-
   phrase((...,seq(Sub),...),S).

seq_subseq(S, Sub) :-
   phrase(subseq(Sub),S).

致谢

...的上述定义的第一次出现在p。

的注释1
  

David B. Searls,用明确的条款语法研究DNA的语言学。 NACLP 1989,第1卷。

答案 1 :(得分:1)

Prolog字符串是列表,其中列表的每个元素是表示所讨论字符的代码点的整数值。字符串"abc" 与列表[97,98,99]完全等效(假设您的prolog实现使用Unicode或ASCII,否则值可能不同)。这导致了这个(从Big-O角度来看可能不是最理想的)解决方案,它基本上说X是S的子串,如果

  • S具有后缀T,以及
  • X是T
  • 的前缀

以下是代码:

substring(X,S) :-
  append(_,T,S) ,
  append(X,_,T) ,
  X \= []
  .

我们将X限制为除空列表之外的其他内容(也就是nil字符串""),因为在概念上可以在任何字符串中找到大量的零长度子字符串:一个长度为的字符串n 有2 +( n -1)个nil子串,一个在字符串中的每个字符之间,一个在第一个字符之前,一个在最后一个字符之后。

答案 2 :(得分:1)

问题在于您的isSubset/2 您尝试在一个谓词中捕获两种不同的情况。要么你正在寻找第一个尝试匹配你的子串的位置,要么你已经找到了这一点并且正在检查字符串是否排列'。

isSubset([], _).
isSubSet(Substring, String) :-
    findStart(Substring, String, RestString),
    line_up(Substring, RestString).

findStart([], String, String).
findStart([H|T], [H|T1], [H|T1]).
findStart(Substring, [_|T], RestString) :-
    findStart(Substring, T, RestString).

line_up([], _).
line_up([H|T], [H|T1]) :-
    line_up(T, T1).

可以将这些组合成一个谓词,如下所示:

isSublist([], L, L).
isSublist([H|T], [H|T1], [H|T1]) :-
    isSublist(T, T1, T1).
isSublist(L, [_|T], Rest) :-
    isSublist(L, T, Rest).

答案 3 :(得分:1)

使用DCG,您可以执行以下操作:(SWI)

%                   anything  substring anything
substr(String) --> ([_|_];[]), String,  ([_|_];[]).

% is X a substring of Y ?
substring(X,Y) :- phrase(substr(X),Y).