c – CYK算法如何工作?
我必须检查一个字符串是否可以从Chomsky正常形式的给定上下文中派生出来.我正在使用C.
关于CYK算法的维基百科文章中有非常好的pseudocode,但我无法理解它. 有人可以通过给我一个CYK算法的伪代码来帮助我,或者解释一下wiki文章中的那个吗? 解决方法
CYK算法将以乔姆斯基正规形式的CFG作为输入.这意味着每个产品都有形式
> S→a,对于某些终端a,或 现在,假设您有一个字符串w,并且您想要查看是否可以从起始符号为S的语法派生它.有两个选项: >如果w是单个字符长,那么解析它的唯一方法是使用S→a形式生成某个字符a.那么看看是否有任何单字符制作符合a. 请注意,这里的选项(2)最终是一个递归解析问题:要查看是否可以从S派生w,看看是否可以从A中导出x和从B中导出y. 有了这个洞察力,这里是递归函数的伪代码,你可以用它来看看非终结符S是否派生了一个字符串w: bool canDerive(nonterminal S,string w) { return canDeriveRec(S,w,w.size()); } /* Can you derive the substring [start,end) of w from S? */ bool canDeriveRec(nonterminal S,string w,int start,int end) { /* Base case: Single characters */ if (end - start == 1) { return whether there is a production S -> a,where a = w[start]; } /* Recursive case: Try all possible splits */ for (each production S -> AB) { for (int mid = start + 1; mid < end; mid++) { if (canDeriveRec(A,start,mid) && canDeriveRec(B,mid,end)) { return true; } } } return false; } 此算法可以正常工作,但如果您绘制出递归的形状,您将找到它 >它会产生大量的冗余递归调用,但是 实际上,不同可能调用的数量是O(n2 N),其中n是输入字符串的长度(对于开始和结束索引的每个可能组合),N是语法中的非终结符号.这些观察结果表明,该算法可以从记忆或动态编程中受益,具体取决于您认为哪种方法更好. 当您采用上述递归算法并记住结果时,或者将上述递归算法转换为动态编程问题时,您可以获得CYK算法. 有O(n2 N)个可能的递归调用.对于每次尝试的生产,它都做O(n)工作.如果对于非终结符号平均存在P个产生,则这意味着整个运行时间为O(n3 NP),对于固定语法而言为O(n3). (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |