String 如何最小化字符串';通过迭代地从字符串中删除某些指定单词的所有匹配项来指定长度
这个问题出现在一次编程竞赛中,我们仍然不知道如何解决它 问题: 给定一个字符串S和一个字符串L列表,我们希望继续删除L中可能出现的所有子字符串。我们必须最小化最终形成的字符串的长度。还要注意,删除字符串可能会引发更多的删除 比如说,String 如何最小化字符串';通过迭代地从字符串中删除某些指定单词的所有匹配项来指定长度,string,algorithm,language-agnostic,substring,String,Algorithm,Language Agnostic,Substring,这个问题出现在一次编程竞赛中,我们仍然不知道如何解决它 问题: 给定一个字符串S和一个字符串L列表,我们希望继续删除L中可能出现的所有子字符串。我们必须最小化最终形成的字符串的长度。还要注意,删除字符串可能会引发更多的删除 比如说, S=ccdededefcde,L={cde} 然后回答=1。因为我们可以通过ccdedefcde->cdefcde->fcde->f来减少S S=aabaab,L={aa,bb}然后回答=0,因为可以通过aabaab->aabb->aa->“空字符串”进行缩减 S=
S=abababaa,L={ABA}
算法
RECURSIVE_FUNCTION ( STRING STR, STRING PATTERN) :
1. STRING LEFT = STR.SUBSTR (0, STR.FIND(PATTERN))
2. STRING RIGHT = STR.SUBSTR(STR.FIND(PATTERN), STR.LENGTH)
3. IF (RIGHT is empty) THEN RETURN LEFT
4. STRING FIN = RECUR(LEFT) + RECUR(RIGHT)
5. RETURN RECUR(FIN)
函数子字符串(A,B)
将返回字符串的子字符串,从包含索引A到包含索引B
操作A+B
是字符串A和B的串联
函数递归(A)
调用相同的函数,也称为递归
示例:ccdededefcde 首先,它将通过
RECUR(左)+RECUR(右)
向下分支:
然后它将在合并时重现(FIN)
:
cdef*
/ \
c def
/
def
*在合并完成之前,将重复执行以下操作:
[cde]f
\
f
最后,根调用返回
f
,这是一个多项式时间算法,可以产生最佳结果。因为这对我来说很方便,所以我将使用多项式时间作为一个子程序,特别是一个扩展,它根据上下文无关语法和加权乘积计算字符串的最小权重解析
A -> N (weight 0)
A -> A C N (weight 0)
N -> N m N c N a N (weight 0)
N -> N p N a N (weight 0)
现在我们只需要用上下文无关语法形式化这个问题。开始符号是A
(通常是S
,但已经使用了),具有以下结果
A -> N (weight 0)
A -> A C N (weight 0)
N -> N m N c N a N (weight 0)
N -> N p N a N (weight 0)
我将很快解释。如果N
和C
是终端,那么A
将接受常规语言N(cn)*
。非终结符C
与单个终结符(字符)匹配
非终结符N
匹配可为空的字符串,即通过删除L
中的字符串可以将其缩减为空字符串的字符串。基本情况是显而易见的
N -> (weight 0)
我们还为L
的每个元素制作了一个产品。例如,当L={mca,pa}
时,我们有以下结果
A -> N (weight 0)
A -> A C N (weight 0)
N -> N m N c N a N (weight 0)
N -> N p N a N (weight 0)
我希望清楚地知道如何在迭代删除和解析之间构建一对一的对应关系,其中解析权重等于剩余字符串的长度。您可以通过维护一组到目前为止遇到的缩减字符串来加速基本的递归深度优先搜索。当您再次看到其中一个时,返回而不是从该字符串重复递归。这个问题很难解决:贪婪的最左端删除算法可能会失败,即使是对于| L |=1的问题实例。S=ABABAA,L={ABA}。最左边的贪婪者将删除[ABA]BAA以离开BAA,不能进一步减少。但是如果你删除AB[ABA]A来获得ABA,那么你可以删除[ABA]来获得空字符串。有一组模式,而不仅仅是一个。困难的是,像你在这里做的那样贪婪地删除子字符串可能会失败:例如,贪婪策略在S=aabababa,L={ABA,AABBAA}时失败。如果你试图删除最左边的ABA,你会得到ABABAA,它可以进一步减少为BAA;但是如果你跳过它并删除下一个,你会得到AABBAA,它可以在下一步被简化为空字符串。事实上,这里有一个问题实例,大小为1的L集仍然无法使用最左边的贪婪删除算法:s=abababaa,L={ABA}。您的算法删除[ABA]ABABAA以获得ABABAA,然后删除[ABA]BAA以离开BAA,不能进一步减少。但是如果你删除ABA[ABA]BAA来获得ababa,然后删除AB[ABA]A来获得ABA,那么第三步可能会将字符串减少为空字符串。除非问题没有要求最佳解决方案,否则通常假设问题正在寻找它。更不用说,这是一个编程竞赛,默认情况下,最佳解决方案是预期的。如果你没有给出一个最优的解决方案,你应该(在答案中)清楚地指出这一点。@Dukeling在文章中指出(CYK正在隐藏一个三元化过程和一个三次全间隔动态程序。)