壞字符規則 - 移動格數:
在$Key裡,尋找和壞字符相同的字。
移動格數:
有找到:壞字符位置 - 找到的位置
沒找到:壞字符位置 - (-1)
比對方向 ←
01234
QQQQABCABC
X
BCABC
01234
壞字符:A
壞字符位置:4
在後續移動過程中,仍有機會和「壞字符A」對齊的字:
位置 4 左邊的字
$Key[0]到 $Key[3]
和壞字符相同的字的位置:2
移動格數:壞字符位置 - 找到的位置
4 - 2 = 2
QQQQABCABC
X
BCABC
$Key移動 →
QQQQABCABC
|
BCABC
找到A對齊,移動2格
比對方向 ←
01234
QQQQBBCABC
X
BCABC
01234
壞字符:B
壞字符位置:4
在後續移動過程中,仍有機會和「壞字符B」對齊的字:
位置 4 左邊的字
$Key[0]到 $Key[3]
和壞字符相同的字的位置:3
移動格數:壞字符位置 - 找到的位置
4 - 3 = 1
QQQQBBCABC
|
BCABC
找到B對齊,移動1格
$Key裡 有 2 個 B
找距離「壞字符」最近的那個
比對方向 ←
01234
QQBBCBBCABC
X
BCABC
01234
壞字符:B
壞字符位置:2
在後續移動過程中,仍有機會和「壞字符B」對齊的字:
位置 2 左邊的字
$Key[0]到 $Key[1]
和壞字符相同的字的位置:0
移動格數:壞字符位置 - 找到的位置
2 - 0 = 2
QQBBCBBCABC
X
BCABC
$Key移動 →
QQBBCBBCABC
|
BCABC
找到B對齊,移動2格
有 2 個B,$Key[0] 和 $Key[3]
只找$Key移動時,會經過壞字符的那個
比對方向 ←
01234
QQQQMBCABC
X
BCABC
01234
壞字符:M
壞字符位置:4
在後續移動過程中,仍有機會和「壞字符M」對齊的字:
位置 4 左邊的字
$Key[0]到 $Key[3]
和壞字符相同的字的位置:沒找到
移動格數:壞字符位置 - 沒找到
4 - (-1) = 5
QQQQMBCABC
X
BCABC
$Key移動 →
QQQQMBCABC
X
BCABC
$Key移動 →
QQQQMBCABC
X
BCABC
$Key移動 →
QQQQMBCABC
X
BCABC
$Key移動 →
QQQQMBCABC
|
BCABC
找不到 M,移動5格
比對方向 ←
01234
QAABCBCABC
X
BCABC
01234
壞字符:A
壞字符位置:1
在後續移動過程中,仍有機會和「壞字符A」對齊的字:
位置 1 左邊的字
$Key[0]
和壞字符相同的字的位置:沒找到
移動格數:壞字符位置 - 找到的位置
1 - (-1) = 2
QAABCBCABC
X
BCABC
$Key移動 →
QAABCBCABC
|
BCABC
找不到 A,移動2格
$Key移動方向、比對方向 - 必須不同
01234
AQQQQBCABC
X
BCABC
$Key移動方向 →
比對方向 →
壞字符:A
壞字符位置:0
之後移動時,$Key的其他字不會經過壞字符A
01234
BCABCAQQQQ
X
BCABC
$Key移動方向 ←
比對方向 →
壞字符:A
壞字符位置:0
之後移動時,$Key的其他字會經過壞字符A,有機會對齊
01234
BCABCQQQQA
X
BCABC
$Key移動方向 ←
比對方向 ←
壞字符:A
壞字符位置:4
之後移動時,$Key的其他字不會經過壞字符A
關於「移動」:
$Key在程式碼中,沒有移動
移動的是$base
模擬製表 $Bc
「壞字符」、「壞字符的位置」是未知的
模擬「各種比對失敗位置」、「各種壞字符」要移動幾格
$Bc[比對失敗位置 ][可能的壞字符]
為表達方便,「可能的壞字符」用string來表示
但實際上,「可能的壞字符」是 int
比對方向 ←
01234
QQQQ BCABC
X
BCABC
01234
$Key[0] 到 $Key[3]之間的字
找距離「壞字符」最近的那個
$Bc[4]['B'] = 4 - 3
$Bc[4]['A'] = 4 - 2
$Bc[4]['C'] = 4 - 1 #不會用到。不過,簡化版會用到
其他字
$Bc[4]['D'] = 4 - (-1)
$Bc[4]['E'] = 4 - (-1)
$Bc[4]['F'] = 4 - (-1)
$Bc[4]['G'] = 4 - (-1)
...
$Bc[4]['Z'] = 4 - (-1)
比對方向 ←
01234
QQQ CBBCABC
X
BCABC
01234
$Key[0] 到 $Key[2]之間的字
找距離「壞字符」最近的那個
$Bc[3]['A'] = 3 - 2
$Bc[3]['C'] = 3 - 1
$Bc[3]['B'] = 3 - 0 #不會用到
其他字
$Bc[3]['D'] = 3 - (-1)
$Bc[3]['E'] = 3 - (-1)
$Bc[3]['F'] = 3 - (-1)
$Bc[3]['G'] = 3 - (-1)
...
$Bc[3]['Z'] = 3 - (-1)
比對方向 ←
01234
QQ BCBBCABC
X
BCABC
01234
$Key[0] 到 $Key[1]之間的字
找距離「壞字符」最近的那個
$Bc[2]['C'] = 2 - 1
$Bc[2]['B'] = 2 - 0
其他字
$Bc[2]['A'] = 2 - (-1) #不會用到
$Bc[2]['D'] = 2 - (-1)
$Bc[2]['E'] = 2 - (-1)
$Bc[2]['F'] = 2 - (-1)
$Bc[2]['G'] = 2 - (-1)
...
$Bc[2]['Z'] = 2 - (-1)
開始製表 $Bc
#設定 $Bc 時,只需要用到 $Key
$Key = 'BCABC'
#設定預設值
#假設$Text $Key裡面只有英文、數字
#陣列的大小為 256
# $B4是一個陣列
# $B4[0] 到 $B4[255] 的值都是 5
$B4 = @( 4 - (-1) ) * 256
# $B3是一個陣列
# $B3[0] 到 $B3[255] 的值都是 4
$B3 = @( 3 - (-1) ) * 256
$B2 = @( 2 - (-1) ) * 256 #都是 3
$B1 = @( 1 - (-1) ) * 256 #都是 2
$B0 = @( 0 - (-1) ) * 256 #都是 1
# $Bc是一個陣列,內含$B0 $B1 $B2 $B3 $B4
$Bc = $B0, $B1, $B2, $B3, $B4
# 設定 $Bc[4]:第一版
#從$Key[3] 到 $Key[0] 是可能的壞字符
for ( $i = 3 ; $i -ge 0 ; $i-- ){
[int]$badChar = $Key[$i]
$Bc[4][ $badChar ] = 4 - $i
}
# 設定 $Bc[4]:第二版
# 當相同字符有兩個以上時,第一次遇到時,才設值
for ( $i = 3 ; $i -ge 0 ; $i-- ){
[int]$badChar = $Key[$i]
#如果是預設值 5 ,表示是第一次遇到
if ($Bc[4][ $badChar ] -eq 5){
$Bc[4][ $badChar ] = 4 - $i
}
}
# 設定 $Bc[4]:第三版
#設值順序改成:從 $Key[0] 到 $Key[3]
#這樣可以不用 if 判斷了
for ( $i = 0 ; $i -le 3 ; $i++ ){ # 0 到 3
[int]$badChar = $Key[$i]
$Bc[4][ $badChar ] = 4 - $i
}
#===== 它們的算法很像 =====
#設定 $Bc[4]
for ( $i = 0 ; $i -le 3 ; $i++ ){ # 0 到 3
[int]$badChar = $Key[$i]
$Bc[4][ $badChar ] = 4 - $i # 4 - $i
}
#設定 $Bc[3]
for ( $i = 0 ; $i -le 2 ; $i++ ){ # 0 到 2
[int]$badChar = $Key[$i]
$Bc[3][ $badChar ] = 3 - $i # 3 - $i
}
#設定 $B[2]
for ( $i = 0 ; $i -le 1 ; $i++ ){ # 0 到 1
[int]$badChar = $Key[$i]
$Bc[2][ $badChar ] = 2 - $i # 2 - $i
}
#===== 原來的版本 =======
$Bc = $B0, $B1, $B2, $B3, $B4
#在 4 比對失敗 移動格數
$Bc[4][ [int][char]$badChar]
#在 3 比對失敗 移動格數
$Bc[3][ [int][char]$badChar]
#===== 簡化的版本 =======
#不用設定 $B0, $B1, $B2, $B3 了
$Bc = $B4
#在 4 比對失敗 移動格數
$Bc[ [int][char]$badChar] - (4 - 4)
#在 3 比對失敗 移動格數
$Bc[ [int][char]$badChar] - (4 - 3)
#在 2 比對失敗 移動格數
$Bc[ [int][char]$badChar] - (4 - 2)
#===== $Bc 簡化版 ======
$Text = 'QQQQQBCABC'
$Key = 'BCABC'
# 製表 $Bc
# $Bc是一個陣列,長度64KB,每個單位的值都是5
$Bc = @( 5 ) * 64KB
for ( $i = 0 ; $i -le 3 ; $i++ ){ # 0 到 3
[int]$badChar = $Key[$i]
$Bc[ $badChar ] = 4 - $i
}
$base = 0
while ($base -lt 6){
# 方向相反
for ($i = 4 ; $i -ge 0 ; $i--){
if ( $Key[$i] -ne $Text[$base + $i] ){ break }
}
if ($i -eq -1 ){ "$Key 在 $base" ; break }
# 移動幾格
[int]$badChar = $Text[$base + $i]
$B_move = $Bc[ $badChar ] - (4 - $i)
#有時 $B_move 值 會是負的。這時需要靠 $Gs[$i]
#$Gs還沒設定,執行此程式碼會出錯
if ( $B_move -gt $Gs[$i] ){
$base += $B_move
}else{
$base += $Gs[$i]
}
}
if ($base -ge 6) { "沒找到"}
沒有留言:
張貼留言