题目:给定一组字符串,要求求出一个最短的字符串:使得它包含所有给出的字符串
例如:比如"a","bc","ca",那么应该得到字符串是"bca"为了让大家明白,再举一个例子:
"cabe", "bef", "abex"----->这三个字串中,输出结果应该是:cabexbef.
<注意了,是最短的字串>
输入字符仅限ASCII码
看看那个的算法最好! 字符数应该可以确定,不过位置似乎有多样性~ 比如第二个例子 befcabex 应该也符合条件… 回复 2# afan
很有意思的问题,为了让大家容易理解,我是把原问题简化说明了下。
大家做做,对训练思维很有帮助的。
我发现本论坛问的问题基本都是‘如何点某个按纽’之类的最初级的问题,很少讨论算法之类的问题
原题目:
===============================================
Name: Shortest Common Superstring 3
Input: A finite set R={r1,r2,...,rm} of binary strings (sequences of 0 and 1); positive integer k.
Question: Is there a binary string w of length at most k such that every string in R is a substring of w, i.e. for each r in R, w can be decomposed as w=w0rw1 where w0, w1 are (possibly empty) binary strings?
=============================================== 字符数应该可以确定,不过位置似乎有多样性~ 比如第二个例子 befcabex 应该也符合条件…
afan 发表于 2011-12-8 01:31 http://www.autoitx.com/images/common/back.gif
的确可能有好几种可能性的答案。
我的思路是:
设字串a是组合x0,x1.....xn的最短公共串
则x0,x1....xn+1的最短公共串是:
若a包含xn+1,返回a
若a不包含xn+1
若a的前m个字符与xn+1的后m个字符相等.....
若a的后m个字符与xn+1的前m个字符相等.....
这个麻烦的在于a可能有好几种可能性
这就得2^n的DP了 我的想法是先按字符串的长度从长到短排序
然后分别从字符串中循环截取一定数量包含头部或包含尾部的字符串进行声明
在之后的字符串中如果整体已声明过则该字符串可以删除
余下的字符串进行收尾相连……
我开始想晕了…… 现在想睡了 zzZ 好玩的东东又来了,试下,也许有缺陷。
#include <array.au3>
Global $out
Local $str = ["cabe", "bef", "abex"]
$fin=simplified($str)
$t=_ArrayToString($fin,"")
MsgBox(0,0,$t)
Func simplified($str)
Local $flag_array, $flag
For $i = 0 To UBound($str) - 2
For $n = $i + 1 To UBound($str) - 1
$flag = StringRegExp($str[$i] & $str[$n], '(\w+)(?=[^\1]*\1)', 3)
If UBound($flag) > 0 Then
ReDim $flag_array
$flag_array = $flag
EndIf
Next
Next
_ArrayDelete($flag_array, 0)
$new = _ArrayUnique($flag_array)
_ArraySort($new)
;~ _ArrayDisplay($str)
;~ _ArrayDisplay($flag_array)
For $i = 1 To 1
$len = StringLen($new[$i])
For $n = 0 To UBound($str) - 1
For $k = $n + 1 To UBound($str) - 1
If StringInStr($str[$n], $new[$i], 1) And StringInStr($str[$k], $new[$i], 1) Then
$out &= $new[$i] & " ==> " & $str[$n] & " VS " & $str[$k] & @CRLF
If (StringRegExp($str[$n], '\b' & $new[$i] & '\w+\b', 0) Or StringRegExp($str[$n], '\b\w+' & $new[$i] & '\b', 0)) And _
(StringRegExp($str[$k], '\b' & $new[$i] & '\w+\b', 0) Or StringRegExp($str[$k], '\b\w+' & $new[$i] & '\b', 0)) Then
$temp = StringRegExp($str[$n] & @CRLF & $str[$k], '\b' & $new[$i] & '\w+\b', 1)
If Not @error Then $left = $temp
$temp = StringRegExp($str[$n] & @CRLF & $str[$k], '\b\w+' & $new[$i] & '\b', 1)
If Not @error Then $right = $temp
;~ MsgBox(0, 0, "$left=" & $left & @CRLF & "$right=" & $right)
$out &= $new[$i] & " ==> " & $str[$n] & " VS " & $str[$k] & @CRLF & $right & StringReplace($left, $new[$i], "") & @CRLF
$str[$n] = $right & StringReplace($left, $new[$i], "")
_ArrayDelete($str, $k)
simplified($str)
EndIf
EndIf
Next
Next
Next
Return $str
EndFunc ;==>simplified
本帖最后由 3mile 于 2011-12-8 14:47 编辑
貌似还有问题,再来:
#include <array.au3>
Global $out
Local $str = ["abcde", "abcd", "abc","abs"]
;~ Local $str = ["bc", "ca", "a"]
;~ Local $str = ["cabe", "bef", "abex","ca","be","efx"]
$fin = simplified($str)
_ArrayDisplay($fin)
$t = _ArrayToString($fin, "")
MsgBox(0, 0, $t)
Func simplified($array)
Local $flag_array, $flag
For $i = 0 To UBound($array) - 2
For $n = $i + 1 To UBound($array) - 1
$flag = StringRegExp($array[$i] & $array[$n], '(\w+)(?=[^\1]*\1)', 3)
If UBound($flag) > 0 Then
ReDim $flag_array
$flag_array = $flag
EndIf
Next
Next
_ArrayDelete($flag_array, 0)
$new = _ArrayUnique($flag_array)
Local $long, $long_len = 0
For $i = 1 To UBound($new) - 1
If StringLen($new[$i]) > $long_len Then
$long = $new[$i]
$long_len = StringLen($long)
EndIf
Next
;~ _ArraySort($new)
;~ _ArrayDisplay($array)
;~ _ArrayDisplay($array)
;~ _ArrayDisplay($flag_array)
For $n = 0 To UBound($array) - 2
For $k = $n + 1 To UBound($array) - 1
Local $right = "", $left = ""
If $k > UBound($array) - 1 Then ContinueLoop
;~
If StringInStr($array[$n], $array[$k]) Then ;Or StringInStr($array[$k],$array[$n]) Then
_ArrayDelete($array, $k)
Return simplified($array)
ElseIf StringInStr($array[$k], $array[$n]) Then
_ArrayDelete($array, $n)
Return simplified($array)
Else
;~ _ArrayDisplay($array,$long)
If (StringRegExp($array[$n], '\b' & $long & '\w+\b', 0) Or StringRegExp($array[$n], '\b\w+' & $long & '\b', 0)) And _
(StringRegExp($array[$k], '\b' & $long & '\w+\b', 0) Or StringRegExp($array[$k], '\b\w+' & $long & '\b', 0)) Then
;~ $temp = StringRegExp($array[$n] & @CRLF & $array[$k], '\b' & $long & '\w+\b', 1)
;~ If Not @error Then $left = $temp
;~
;~ $temp = StringRegExp($array[$n] & @CRLF & $array[$k], '\b\w+' & $long & '\b', 1)
;~ If Not @error Then $right = $temp
;~
;~ $array[$n] = $right & StringReplace($left, $long, "")
$temp0 = StringRegExpReplace($array[$n] & $array[$k], '(\w+)\1', '\1')
$temp1 = StringRegExpReplace($array[$k] & $array[$n], '(\w+)\1', '\1')
If StringLen($temp0)<StringLen($temp1) Then
$array[$n] =$temp0
_ArrayDelete($array, $k)
Return simplified($array)
Else
$array[$n] =$temp0
_ArrayDelete($array, $k)
Return simplified($array)
EndIf
EndIf
EndIf
Next
Next
Return $array
EndFunc ;==>simplified
貌似还有问题,再来:
3mile 发表于 2011-12-8 14:27 http://www.autoitx.com/images/common/back.gif
似乎有点问题哦,试试$str = ['abc', 'bcde', 'gga'] 本帖最后由 afan 于 2011-12-8 21:04 编辑
以下为我的题解,还可以得到所有符合条件的组合:
**** Hidden Message ***** 再来
#include <array.au3>
Global $out
;~ Local $str = ["abcde", "abcd", "abc","abs"]
;~ Local $str = ["bc", "ca", "a"]
;~ Local $str = ["cabe", "bef", "abex","ca","be","efx"]
Local $str = ['abc', 'bcde', 'gga']
$fin = simplified($str)
_ArrayDisplay($fin)
$t = _ArrayToString($fin, "")
MsgBox(0, 0, $t)
Func simplified($array)
Local $flag_array, $flag
For $i = 0 To UBound($array) - 2
For $n = $i + 1 To UBound($array) - 1
$flag = StringRegExp($array[$i] & $array[$n], '(\w+)(?=[^\1]*\1)', 3)
If UBound($flag) > 0 Then
ReDim $flag_array
$flag_array = $flag
EndIf
Next
Next
_ArrayDelete($flag_array, 0)
$new = _ArrayUnique($flag_array)
Local $long, $long_len = 0
For $i = 1 To UBound($new) - 1
If StringLen($new[$i]) > $long_len Then
$long = $new[$i]
$long_len = StringLen($long)
EndIf
Next
;~ _ArraySort($new)
;~ _ArrayDisplay($array)
;~ _ArrayDisplay($array)
;~ _ArrayDisplay($flag_array)
For $n = 0 To UBound($array) - 2
For $k = $n + 1 To UBound($array) - 1
Local $right = "", $left = ""
If $k > UBound($array) - 1 Then ContinueLoop
;~
If StringInStr($array[$n], $array[$k]) Then ;Or StringInStr($array[$k],$array[$n]) Then
_ArrayDelete($array, $k)
Return simplified($array)
ElseIf StringInStr($array[$k], $array[$n]) Then
_ArrayDelete($array, $n)
Return simplified($array)
Else
;~ _ArrayDisplay($array,$long)
If (StringRegExp($array[$n], '\b' & $long & '\w+\b', 0) Or StringRegExp($array[$n], '\b\w+' & $long & '\b', 0)) And _
(StringRegExp($array[$k], '\b' & $long & '\w+\b', 0) Or StringRegExp($array[$k], '\b\w+' & $long & '\b', 0)) Then
;~ $temp = StringRegExp($array[$n] & @CRLF & $array[$k], '\b' & $long & '\w+\b', 1)
;~ If Not @error Then $left = $temp
;~
;~ $temp = StringRegExp($array[$n] & @CRLF & $array[$k], '\b\w+' & $long & '\b', 1)
;~ If Not @error Then $right = $temp
;~
;~ $array[$n] = $right & StringReplace($left, $long, "")
$temp0 = StringRegExpReplace($array[$n] & $array[$k], '(?<!'&$array[$n]&')(\w+)\1', '\1')
$temp1 = StringRegExpReplace($array[$k] & $array[$n], '(?<!'&$array[$k]&')(\w+)\1', '\1')
If StringLen($temp0)<StringLen($temp1) Then
$array[$n] =$temp0
_ArrayDelete($array, $k)
Return simplified($array)
Else
$array[$n] =$temp0
_ArrayDelete($array, $k)
Return simplified($array)
EndIf
EndIf
EndIf
Next
Next
Return $array
EndFunc ;==>simplified
回复 10# 3mile
貌似还是有点问题,用9#的字符串测试,得到的输出为 abcdegga ,正确的应该是 ggabcde 回复 11# afan
最后试下:
#include <array.au3>
Global $out
Local $ts = TimerInit()
;~ Local $str = ["abcde", "abcd", "abc","abs"]
;~ Local $str = ["bc", "ca", "a"]
Local $str = ["cabe", "bef", "abex","ca","be","efx"]
;~ Local $str = ['gga', 'bcde', 'abc']
_ArraySort($str)
$fin = simplified($str)
;~ _ArrayDisplay($fin)
$t = _ArrayToString($fin, "")
MsgBox(0, TimerDiff($ts), $t)
Func simplified($array)
Local $flag_array, $flag
For $i = 0 To UBound($array) - 2
For $n = $i + 1 To UBound($array) - 1
$flag = StringRegExp($array[$i] & $array[$n], '(\w+)(?=[^\1]*\1)', 3)
If UBound($flag) > 0 Then
ReDim $flag_array
$flag_array = $flag
EndIf
Next
Next
_ArrayDelete($flag_array, 0)
$new = _ArrayUnique($flag_array)
Local $long, $long_len = 0
For $i = 1 To UBound($new) - 1
If StringLen($new[$i]) > $long_len Then
$long = $new[$i]
$long_len = StringLen($long)
EndIf
Next
;~ _ArraySort($new)
;~ _ArrayDisplay($array)
;~ _ArrayDisplay($array)
;~ _ArrayDisplay($flag_array)
For $n = 0 To UBound($array) - 2
For $k = $n + 1 To UBound($array) - 1
Local $right = "", $left = ""
If $k > UBound($array) - 1 Then ContinueLoop
;~
If StringInStr($array[$n], $array[$k]) Then ;Or StringInStr($array[$k],$array[$n]) Then
_ArrayDelete($array, $k)
Return simplified($array)
ElseIf StringInStr($array[$k], $array[$n]) Then
_ArrayDelete($array, $n)
Return simplified($array)
Else
;~ _ArrayDisplay($array,$long)
If (StringRegExp($array[$n], '\b' & $long & '\w+\b', 0) Or StringRegExp($array[$n], '\b\w+' & $long & '\b', 0)) And _
(StringRegExp($array[$k], '\b' & $long & '\w+\b', 0) Or StringRegExp($array[$k], '\b\w+' & $long & '\b', 0)) Then
;~ $temp = StringRegExp($array[$n] & @CRLF & $array[$k], '\b' & $long & '\w+\b', 1)
;~ If Not @error Then $left = $temp
;~
;~ $temp = StringRegExp($array[$n] & @CRLF & $array[$k], '\b\w+' & $long & '\b', 1)
;~ If Not @error Then $right = $temp
;~
;~ $array[$n] = $right & StringReplace($left, $long, "")
$temp0 = StringRegExpReplace($array[$n] &";"& $array[$k], '(\w+)(?=;\1)', '')
$temp1 = StringRegExpReplace($array[$k] &";"& $array[$n], '(\w+)(?=;\1)', '')
If StringLen($temp0)<StringLen($temp1) Then
$array[$n] =StringReplace($temp0,";","")
_ArrayDelete($array, $k)
;~ _ArrayDisplay($array)
Return simplified($array)
Else
$array[$n] =StringReplace($temp1,";","")
_ArrayDelete($array, $k)
;~ _ArrayDisplay($array)
Return simplified($array)
EndIf
EndIf
EndIf
Next
Next
Return $array
EndFunc ;==>simplified
换个思路看下
#include <Array.au3>
;~ Local $aArray = ["abcde", "abcd", "abc","abs"];['gga', 'bcde', 'abc']
Local $aArray = ['gga', 'bcde', 'abc']
;~ Local $aArray = ["bc", "ca", "a"]
;~ Local $aArray = ["cabe", "bef", "abex","ca","be","efx"]
Local $k=1
$aNewArray = _ArrayPermute($aArray, ",") ;使用默认参数
For $i=1 To UBound($aNewArray)-1
$aNewArray[$i]=StringRegExpReplace($aNewArray[$i],'(\w+)(?=,\1)','')
$aNewArray[$i]=StringFormat('%010s',StringReplace($aNewArray[$i],",",""))
Next
_ArraySort($aNewArray,0,1)
For $i=1 To UBound($aNewArray)-2
$aNewArray[$i]=StringRegExpReplace($aNewArray[$i],'^0+','')
$aNewArray[$i+1]=StringRegExpReplace($aNewArray[$i+1],'^0+','')
ConsoleWrite(StringLen($aNewArray[$i])&@TAB&StringLen($aNewArray[$i+1])&@CRLF)
If StringLen($aNewArray[$i])=StringLen($aNewArray[$i+1]) Then
$k+=1
Else
ExitLoop
EndIf
Next
$out=_ArrayToString($aNewArray,@CRLF,1,$k)
MsgBox(0,0,$out) 来学习了! 看看啥内容哈
页:
[1]
2