SA-IS æ³ã®ã¡ã¢
suffix array ãç·å½¢æéã§æ§ç¯ãã SA-IS æ³ã«ã¤ãã¦ã®ã¡ã¢ã§ãã
SA-IS æ³ã®è§£èª¬ã¯ããã¨ä¸ã®ä¸ã«ãã£ã±ãããã¾ãããå®éã®ããã°ã©ã ã«ããæ¹æ³ãããããããªã£ãããã©ããã¦ããã§ãã¾ãè¡ãã®ãæ¸ããã¦ãªãã¦æ°æã¡æªãã£ãããããã®ãå¤ãã¦ãèªåã®æãæãã®ãã®ãããã¾ããã§ãããã¢ã«ã´ãªãºã ã¯å½ç¶ããã°ã©ã ã§è¦ããããå³å¯ãªè¨¼æã¯è¦ããªããã©ç´è¦³çãªçç±ã¯ç¥ãããã
ã¨ãããã¨ã§ãèªåãªãã®ç解ãæ¸ãã¦ã¿ã¾ããã
suffix array ã¨ã¯
æååã® suffix ã¨ã¯ãæååã®éä¸ããæå¾ã¾ã§ã®é¨åæååã®ãã¨ã§ããé¡æã®æååã "mmiissiissiippii" ã¨ããã¨ã次㮠17 åã®é¨åæååã§ãã
0 mmiissiissiippii$ 1 miissiissiippii$ 2 iissiissiippii$ 3 issiissiippii$ 4 ssiissiippii$ 5 siissiippii$ 6 iissiippii$ 7 issiippii$ 8 ssiippii$ 9 siippii$ 10 iippii$ 11 ippii$ 12 ppii$ 13 pii$ 14 ii$ 15 i$ 16 $
æå¾ã® $ ã¯çªå µã§ãã
ãããæ®éã«è¾æ¸é ã«ã½ã¼ããã¾ããæåã«ã¯æ®éã«å ¨é åºããããçªå µã¯ä»ã®ã©ã®æåãããå°ããã¨ãã¾ãã
16 $ 15 i$ 14 ii$ 10 iippii$ 6 iissiippii$ 2 iissiissiippii$ 11 ippii$ 7 issiippii$ 3 issiissiippii$ 1 miissiissiippii$ 0 mmiissiissiippii$ 13 pii$ 12 ppii$ 9 siippii$ 5 siissiippii$ 8 ssiippii$ 4 ssiissiippii$
ãã®ã¨ãã®ã¤ã³ããã¯ã¹ã®åã[16, 15, 14, 10, 6, 2, 11, 7, 3, 1, 0, 13, 12, 9, 5, 8, 4] ã suffix array ã¨ããã¾ããä»å説æãã¾ããããsuffix array ã¯æ¤ç´¢ãå§ç¸®ãªã©ã§ããããã¨å½¹ç«ã¤æ°åã§ãã
suffix array ãæ±ããããã°ã©ã ã Ruby ã§ãã¤ã¼ãã«æ¸ãã¨ãããã ãã§ãã
s = "mmiissiissiippii".bytes + [0] p (0...s.size).sort_by {|i| s[i..-1] } #=> [16, 15, 14, 10, 6, 2, 11, 7, 3, 1, 0, 13, 12, 9, 5, 8, 4]
ãã®ããã°ã©ã ã¯ãã½ã¼ãã« O(n log n) ããããåæ¯è¼ã« O(n) ããããã®ã§ãå ¨ä½ã§ O(n^2 log n) ããããã¾ããSA-IS ã¯ããã O(n) ã§ãã£ã¦ãã¾ãã¾ãããããã
SA-IS æ³ã®è¶ æ¦è¦
æµãã¨ãã¦ã¯ã次ã®ãããªæãã®ã¢ã«ã´ãªãºã ã§ãã
- é©å½ãªã種ããå ã«ãinduced sort ã¨ããã®ããã â ééã£ã suffix array ãå¾ããã
- ééã£ã suffix array ã使ã£ã¦ãæ£ããã種ããå¾ã
- æ£ããã種ããå ã«ãinduced sort ãããä¸åº¦ãã â æ£ãã suffix array ãå¾ããã
ã種ããä½ãã¯ãã¨ã§èª¬æããã¨ãã¦ãæåã®ç®æ¨ã¯ induced sort ã¨ãããã®ãç解ãããã¨ã§ããããã induced sort ãç解ããã«ã¯ããL å㨠S åããLMSãããã³ãã¨ããæ¦å¿µãã¾ãç解ããå¿ è¦ãããã¾ããé ã«èª¬æãã¾ãã
L å㨠S å
æåå s ã®ã¤ã³ããã¯ã¹ i ããå§ã¾ã suffix ã s[i..] ã¨æ¸ããã¨ã«ãã¾ããs[0..] = "mmiissiissiippii$" ã§ãã
åã¤ã³ããã¯ã¹ãã次ã®ã«ã¼ã«ã§ L å㨠S åã«åãã¾ãã
- æå¾ï¼çªå µï¼ã®ã¤ã³ããã¯ã¹ã¯ S å
- s[i..] > s[i+1..] ã ã£ããã¤ã³ããã¯ã¹ i 㯠L åï¼i 㯠i+1 ãã Largerï¼
- s[i..] < s[i+1..] ã ã£ããã¤ã³ããã¯ã¹ i 㯠S åï¼i 㯠i+1 ãã Smallerï¼
ãã¤ã³ããã¯ã¹ i ã L åãã¨è¨ã£ããããs[i..] ã L åãã¨è¨ã£ãããã¾ãããªãããã¹ã¦ã® suffix ã¯é·ããç°ãªãã®ã§ãs[i..] == s[i+1..] ã«ãªããã¨ã¯ããã¾ããã
ä¾é¡ã®æååãåé¡ããã¨æ¬¡ã®éãã
mmiissiissiippii$ LLSSLLSSLLSSLLLLS
ãããè¨ç®ããã«ã¯ãæååãéé ã«èµ°æ»ãã¦æ±ºãã¦ããã°ããã§ããåºæ¬çã« s[i] 㨠s[i+1] ã®æåãæ¯ã¹ã¦æ±ºãã¦ããã¾ãã
# é¡æã®æåå s = "mmiissiissiippii".bytes + [0] k = 256 # æå種ã®æ° # L åã S åã t = [nil] * s.size # æå¾ã¯ S t[-1] = :S (s.size - 2).downto(0) do |i| # s[i] < s[i+1] ãªãæããã« s[i..] < s[i+1..] => i 㯠S å # s[i] > s[i+1] ãªãæããã« s[i..] > s[i+1..] => i 㯠L å # s[i] == s[i+1] ã®å ´åãs[i..] <=> s[i+1..] ã®æ¯è¼çµæ㯠# s[i+1..] <=> s[i+2..] ã«æºãã (ã¤ã¾ã t[i + 1] ã¨åã) case when s[i] < s[i + 1] then t[i] = :S when s[i] > s[i + 1] then t[i] = :L else t[i] = t[i + 1] end end
LMS 㨠LMS é¨åæåå
ã¤ã³ããã¯ã¹ i - 1 ã L åãi ã S åã«ãªã£ã¦ããã¨ããi ã LMSï¼Left-most S, æã左㮠Sï¼ã¨è¨ãã¾ãã
ä¾é¡ã§è¨ãã°ã2 çªç®ã6 çªç®ã10 çªç®ã16 çªç®ã LMS ãå°ãã¤ããä½ç½®ã
1111111 01234567890123456 mmiissiissiippii$ LLSSLLSSLLSSLLLLS ^ ^ ^ ^ <= LMS ã®ã¤ã³ããã¯ã¹
ã¤ãã§ã«ãLMS ãã次㮠LMS ã¾ã§ã®é¨åæååã LMS é¨åæååã¨è¨ãã¾ããããã¯ã ãã¶å¾ã§åºã¦ãã¾ãã
mmiissiissiippii$ LLSSLLSSLLSSLLLLS ^ ^ ^ ^ iissi <= LMS é¨åæåå iissi <= LMS é¨åæåå iippii$ <= LMS é¨åæåå $ <= LMS é¨åæåå
ãã³
ã¾ããæåå s ã¨åãé·ãã®é å sa ãç¨æãã¾ããããã« suffix array ã®æ°åãå ¥ããã®ãç®æ¨ã§ãã
# ä½æ¥é å sa = [nil] * s.size
åé ã® suffix array ãè¦ãã¨ãi ã§å§ã¾ã suffix 㯠1 çªç®ãã 8 çªç®ãm ã§å§ã¾ã suffix 㯠9 çªç®ãã 10 çªç®ãã¨ããããã«ãsuffix ã®å é ã®æåãã¨ã«ç¯å²ã決ã¾ã£ã¦ãã¾ãããã®ç¯å²ããæåã®ããã³ãã¨ããã¾ãããã¨ãã°ããæå i ã®ãã³ã㯠1 çªç®ãã 8 çªç®ã§ãã
ãã®ãã³ã¯ãæåå s ã®ä¸ã®åæåã®åºç¾åæ°ãæ°ããã°ãããã¾ãã
# s ã«åºç¾ããæå種ãã¨ã®ã«ã¦ã³ã bin = [0] * (k + 1) s.each {|ch| bin[ch + 1] += 1 } # æå種ãç´¯ç©ãããã¨ã§ bin ã®ã¤ã³ããã¯ã¹ã決ãã sum = 0 bin = bin.map {|v| sum += v }
ããã«ãã£ã¦ãæå ch ã§å§ã¾ã suffix ã¯ãsa ã® bin[ch] çªç®ãã bin[ch+1] - 1 çªç®ã®ã©ããã«å ¥ããã°ãããã¨ãããã¨ã«ãªãã¾ãã
ãããããL åã® suffix 㨠S åã® suffix ãåããã³ã«å ¥ãå ´åï¼ã¤ã¾ãå é ã®æåãåãå ´åï¼ãå¿ ã L åã®æ¹ãåã«å ¥ãããã¨ã«ãªãã¾ããçç±ã¯â*1
ã¨ãããã¨ã§ãé å sa ã次ã®ããã«è¡¨ç¾ãããã¨ã«ãã¾ãã
0 $ S : -- 1 i L : -- 2 i L : -- 3 i S : -- 4 i S : -- 5 i S : -- 6 i S : -- 7 i S : -- 8 i S : -- 9 m L : -- 10 m L : -- 11 p L : -- 12 p L : -- 13 s L : -- 14 s L : -- 15 s L : -- 16 s L : --
左端ã®æ°å㯠sa å ã®ã¤ã³ããã¯ã¹ããã®å³ã®æåã¯ãã³ãããã«ãã®å³ã®æå㯠L åã S åãã表ãã¦ã¾ãããã¨ãã°ãi ã§å§ã¾ã S åã® suffix 㯠3 çªç®ãã 8 çªç®ã®ã©ããã«å ¥ãã¾ããinduced sort ã§ã¯ããã®ã«ã¼ã«ãæºããããã« suffix ã®ã¤ã³ããã¯ã¹ãå ¥ãã¦ããã¾ãã
induced sort
ããããæåã®ç®æ¨ã§ãã£ã induced sort ã®èª¬æã«å ¥ãã¾ããinduced sort 㯠3 ã¤ã®æ®µéãããªãã¾ãã
- LMS ã®ã¤ã³ããã¯ã¹ããã³ã®çµããããè©°ãã¦ãã
- L åã®ã¤ã³ããã¯ã¹ããã³ã®é ããè©°ãã¦ãã
- S åã®ã¤ã³ããã¯ã¹ãï¼LMS ãå«ãã¦å度ï¼ãã³ã®çµããããè©°ãã¦ãã
ã¨ããããã¢ã«ã´ãªãºã ã説æãã¦ããããããããã ãããä½ããã£ã¦ããã説æãã¾ãã
induced sort: ã¹ããã 1
ã¹ããã 1 ã¯ãLMS ã®ã¤ã³ããã¯ã¹ãè©°ãã¦ããã¾ããLMS ã® 2 ã6 ã10 ã16 ãããããã i ãi ãi ã$ ã®ãã³ã«çµããããå ¥ãã¾ãã
0 $ S : 16 $ 1 i L : -- 2 i L : -- 3 i S : -- 4 i S : -- 5 i S : -- 6 i S : 2 iissiissiippii$ 7 i S : 6 iissiippii$ 8 i S : 10 iippii$ 9 m L : -- 10 m L : -- 11 p L : -- 12 p L : -- 13 p L : -- 14 p L : -- 15 s L : -- 16 s L : --
å³ç«¯ã«ãã¤ã³ããã¯ã¹ããå§ã¾ã suffix ãåèã«æ¸ãã¦ãã¾ãã
ã¹ããã 1 ã Ruby ã§æ¸ãã¨ãããªæãã
# ã¤ã³ããã¯ã¹ i ã LMS ãã©ãã def lms?(t, i) i > 0 && t[i - 1] == :L && t[i] == :S end # LMS ã®ã¤ã³ããã¯ã¹ã ãåãåºãããªã¹ãï¼ã種ãï¼ lmss = (0...s.size).select {|i| lms?(t, i) } # ã¹ããã 1: LMS ã®ã¤ã³ããã¯ã¹ããã³ã®çµããã®æ¹ããå ¥ãã count = [0] * k # ãã³ãã¨ã«ãã§ã«æ¿å ¥ããæ°ãã«ã¦ã³ããã # æ¿å ¥ããé åºã¯é©å½ lmss.reverse_each do |i| ch = s[i] # ch ãå ¥ãããã³ã®çµãã (bin[ch + 1] - 1) ããè©°ãã¦ããã sa[bin[ch + 1] - 1 - count[ch]] = i count[ch] += 1 end
å®ã¯ãã®ã¨ããLMS ãã©ãããé åºã§æ¿å ¥ãããããè¶ æ¦è¦ã§è¨ã£ã¦ããã種ãã§ããæ£ããé 㧠LMS ãæ¿å ¥ããã°ãinduced sort ã«ãã£ã¦æ£ãã suffix array ãè¨ç®ã§ãã¦ãã¾ãã¾ãããããããã®æç¹ã§æ£ããé åºã¯ããããªãã®ã§ãé©å½ã« 2 ã6 ã10 ã¨ä¸¦ã¹ã¾ãããæ£ããã¯ä¸ãã 10 ã6 ã2 ã®é ã«ãªããªãã¨ãããªãã®ã§ãä¸æ£è§£ã§ããæçµçãªçµæãééã£ããã®ã«ãªãã¾ãããããä¸æè°ãªãã¨ã«ããã®ééã£ãçµæãããæ£ããã種ããæ½åºã§ããã®ã§ãã詳ããã¯å¾ã§ã
induced sort: ã¹ããã 2
ã¹ããã 2 ã¯ãsa ãæ£é ã«èµ°æ»ã㦠L åã® suffix ãåãã¦ããã¾ãã
ã¾ããsa ã«å ¥ã£ã¦ããæåã®ã¤ã³ããã¯ã¹ã¯ 16 ã§ãããã® 1 ã¤åã®ã¤ã³ããã¯ã¹ 15 㯠L åãªã®ã§ãã¹ããã 2 ã§æ±ã対象ã§ããs[15] 㯠i ãªã®ã§ i ã®ãã³ã«å ¥ãã¾ãããã®ã¨ãããã³ã®é ã«è©°ãã¾ãã
0 $ S : 16 $ <===== ä»è¦ã¦ããã¨ãã 1 i L : 15 i$ <===== æ¿å ¥ä½ç½® 2 i L : -- 3 i S : -- 4 i S : -- 5 i S : -- 6 i S : 2 iissiissiippii$ 7 i S : 6 iissiippii$ 8 i S : 10 iippii$ 9 m L : -- 10 m L : -- 11 p L : -- 12 p L : -- 13 p L : -- 14 p L : -- 15 s L : -- 16 s L : --
ãã®ã¨ãããæ¿å ¥ä½ç½®ãã¯å¿ ããä»è¦ã¦ããã¨ãããããå¾ã«æ¥ã¾ããçç±â*2
次ã¯ãå ¥ããã°ããã® 15 ã§ãã14 ã L åãªã®ã§å ¥ãã¾ãããããç¹°ãè¿ãã¦ããã¨ãæçµçã«æ¬¡ã®ããã«ãªãã¾ãã
0 $ S : 16 $ 1 i L : 15 i$ 2 i L : 14 ii$ 3 i S : -- 4 i S : -- 5 i S : -- 6 i S : 2 iissiissiippii$ 7 i S : 6 iissiippii$ 8 i S : 10 iippii$ 9 m L : 1 miissiissiippii$ 10 m L : 0 mmiissiissiippii$ 11 p L : 13 pii$ 12 p L : 12 ppii$ 13 s L : 5 siissiippii$ 14 s L : 9 siippii$ 15 s L : 4 ssiissiippii$ 16 s L : 8 ssiippii$
ã¹ããã 2 ã Ruby ã§æ¸ãã¨ãããªæãã
# ã¹ããã 2: sa ãæé ã«èµ°æ»ãã¦ãã count = [0] * k # ãã³ãã¨ã«ãã§ã«æ¿å ¥ããæ°ãã«ã¦ã³ããã sa.each do |i| next if i == nil next if i == 0 next if t[i - 1] == :S # sa ã«å ¥ã£ã¦ããã¤ã³ããã¯ã¹ i ã«ã¤ãã¦ãi - 1 ã L åã§ããã¨ãã # æå s[i - 1] ã«å¯¾å¿ãããã³ã« i - 1 ãé ããè©°ãã¦ããã ch = s[i - 1] sa[bin[ch] + count[ch]] = i - 1 count[ch] += 1 end
induced sort: ã¹ããã 3
ã¹ããã 3 ã¯ãsa ãéé ã«ææ»ã㦠S åã® suffix ãåãã¦ããã¾ããLMS ã S åã®ä¸ç¨®ãªã®ã§åããªããã¾ãã
ã¾ããsa ã®æå¾ã«å ¥ã£ã¦ããã¤ã³ããã¯ã¹ã¯ 8 ã§ãããã® 1 ã¤åã®ã¤ã³ããã¯ã¹ 7 㯠S åãªã®ã§åãã¾ããs[7] 㯠i ãªã®ã§ i ã®ãã³ã«å ¥ãã¾ãããã®ã¨ãããã³ã®çµããããè©°ãã¦ããã¾ãã
0 $ S : 16 $ 1 i L : 15 i$ 2 i L : 14 ii$ 3 i S : -- 4 i S : -- 5 i S : -- 6 i S : 2 iissiissiippii$ 7 i S : 6 iissiippii$ 8 i S : 7 issiippii$ <===== æ¿å ¥ä½ç½® 9 m L : 1 miissiissiippii$ 10 m L : 0 mmiissiissiippii$ 11 p L : 13 pii$ 12 p L : 12 ppii$ 13 s L : 5 siissiippii$ 14 s L : 9 siippii$ 15 s L : 4 ssiissiippii$ 16 s L : 8 ssiippii$ <===== ä»è¦ã¦ããã¨ãã
ã¹ããã 2 ã¨åãããã«ããæ¿å ¥ä½ç½®ãã¯å¿ ããä»è¦ã¦ããã¨ãããããåã«æ¥ã¾ããçç±ãåæ§ã§ãã
ãªãããã¨ãã¨å ¥ã£ã¦ãã 10 ãæ¸ãã¤ã¶ãã¦ãããã¨ã«æ³¨æãæåããå ¥ã£ã¦ãã LMS ã¯ï¼"$" ãé¤ãã¦ï¼ãã£ããå ¨é¨æ¸ãã¤ã¶ããããã®å¾ã§åæ¿å ¥ããã¾ããçç±ã¯æ¬¡ã®ç¯ã§ã
ãããç¹°ãè¿ãã¨ãæçµçã«æ¬¡ã®ããã«ãªãã¾ãã
0 $ S : 16 $ 1 i L : 15 i$ 2 i L : 14 ii$ 3 i S : 10 iippii$ 4 i S : 2 iissiissiippii$ 5 i S : 6 iissiippii$ 6 i S : 11 ippii$ 7 i S : 3 issiissiippii$ 8 i S : 7 issiippii$ 9 m L : 1 miissiissiippii$ 10 m L : 0 mmiissiissiippii$ 11 p L : 13 pii$ 12 p L : 12 ppii$ 13 s L : 5 siissiippii$ 14 s L : 9 siippii$ 15 s L : 4 ssiissiippii$ 16 s L : 8 ssiippii$
確ãã« LMS ã® 2 㨠6 㨠10 ãï¼å ã¨ç°ãªãä½ç½®ã«ï¼æ¿å ¥ããã¦ãã¾ãã
ãããã¦å¾ããã sa ã¯ãã»ã¼ã½ã¼ãããã¦ããããã«è¦ãã¾ãããä¸é¨ééã£ã¦ãã¾ããä¾ãã°ãs[4..] = "ssiissiippii$" ã 15 çªç®ãs[8..] = "ssiippii$" ã 16 çªç®ã«æ¥ã¦ãã¾ããããã®é åºã¯éã§ãããããã¯å¾ã§ç´ãã¾ãã
Ruby ã¯ãã¡ãã
# ã¹ããã 3: sa ãéé ã«èµ°æ»ãã¦ãã count = [0] * k # ãã³ãã¨ã«ãã§ã«æ¿å ¥ããæ°ãã«ã¦ã³ããã sa.reverse_each do |i| next if i == nil next if i == 0 next if t[i - 1] == :L # sa ã«å ¥ã£ã¦ããã¤ã³ããã¯ã¹ i ã«ã¤ãã¦ãi - 1 ã S åã§ããã¨ãã # æå s[i - 1] ã«å¯¾å¿ãããã³ã« i - 1 ãçµããããè©°ãã¦ããã ch = s[i - 1] sa[bin[ch + 1] - 1 - count[ch]] = i - 1 # ä¸æ¸ããããã¨ããã count[ch] += 1 end
induced sort ã®çµæã®èå¯
induced sort ãããã¨ãããã®çµæã¯ã©ããªæ§è³ªãæºããã¦ããã§ããããã
ã¹ããã 1 ã¯ãã³ã½ã¼ããªã®ã§ãå°ãªãã¨ãå suffix ã®æåã®æåã«ã¤ãã¦ã¯ã¡ããã¨ã½ã¼ãã§ãã¦ãã¾ããããããå suffix ã® 2 æåç®ä»¥éã¯ã½ã¼ãããã¦ããªãããããã¾ããã次ã®å³ã¯ã¹ããã 1 ã®çµæã§ãã½ã¼ãããã¦ããªããããããªãã¨ããã ... ã§çç¥ãã¦è¡¨ç¤ºãã¦ãã¾ãã
0 $ S : 16 $ 1 i L : -- 2 i L : -- 3 i S : -- 4 i S : -- 5 i S : -- 6 i S : 2 i... 7 i S : 6 i... 8 i S : 10 i... 9 m L : -- 10 m L : -- 11 p L : -- 12 p L : -- 13 s L : -- 14 s L : -- 15 s L : -- 16 s L : --
ã¹ããã 2 ã§ã¯ããã§ã«å ¥ã£ã¦ãã suffix ãã 1 ã¤é·ã suffix ãå ¥ãã¦ããã¾ãããã®ã¨ããå é n æåã«ã¤ãã¦ã½ã¼ãããã¦ãã suffix ã 1 ã¤ä¼¸ã°ãã suffix ã¯ãå é n + 1 æåãã½ã¼ãããã¦ãããã¨ãä¿è¨¼ããã¾ããçç±â*3
ãããç¹°ãè¿ãã¨ãã¹ããã 2 å®äºæç¹ã§æ¬¡ã®ããã«ãªãã¾ãã
0 $ S : 16 $ 1 i L : 15 i$ 2 i L : 14 ii$ 3 i S : -- 4 i S : -- 5 i S : -- 6 i S : 2 i... 7 i S : 6 i... 8 i S : 10 i... 9 m L : 1 mi... 10 m L : 0 mmi... 11 p L : 13 pii$ 12 p L : 12 ppii$ 13 s L : 5 si... 14 s L : 9 si... 15 s L : 4 ssi... 16 s L : 8 ssi...
ã¹ããã 3 ã¯ã¹ããã 2 ã¨å ¨ãåæ§ã§ãã
0 $ S : 16 $ 1 i L : 15 i$ 2 i L : 14 ii$ 3 i S : 10 iippii$ 4 i S : 2 iissi... 5 i S : 6 iissi... 6 i S : 11 ippii$ 7 i S : 3 issi... 8 i S : 7 issi... 9 m L : 1 mi... 10 m L : 0 mmi... 11 p L : 13 pii$ 12 p L : 12 ppii$ 13 s L : 5 si... 14 s L : 9 si... 15 s L : 4 ssi... 16 s L : 8 ssi...
ã¨ãããã¨ã§ã... ã«ãªã£ã¦ããªãé¨åã«ã¤ãã¦ã¯ã½ã¼ãããã¦ãããã¨ãä¿è¨¼ããã¾ããããã induced sort ã«ãã£ã¦è¨ãããã¨ã
ãã¦ããããã¹ããã 1 ã®æ®µéã§ãLMS ãæ£ããé åºï¼ã種ãï¼ã§æ¿å ¥ããã¦ããã¨ãã¾ããã¹ããã 2 ã¨ã¹ããã 3 ã®ãå é n æåã«ã¤ãã¦ã½ã¼ãããã¦ãã suffix ãå ã«ã1 ã¤é·ã suffix ãå é n + 1 æåã«ã¤ãã¦ã½ã¼ããããç¶æ ã§æ¿å ¥ãããã¨ããæ§è³ªãããæ£ããã種ãããå§ãã¦æçµçã«å¾ããã sa ã¯ããã¹ã¦ã® suffix ã®å ¨ä½ã«ã¤ãã¦ã½ã¼ãããã¦ãããã¨ã«ãªãã¾ããããã¯ããªãã¡ãæ£ãã suffix array ã§ãã
ã¨ãããã¨ã§ãã©ãã«ãæ£ããã種ããå¾ãã¨ããã®ãæ®ã課é¡ã§ããå®ã¯ããã¯ãä¸è¨ã®ãééã£ã induced sort ã®çµæãã使ã£ã¦åãåºããã¨ãã§ããã®ã§ããããã®åã«æ£ããã種ãã¨ã¯ä½ããèå¯ãã¾ãã
æ£ããã種ã
æ£ããã種ããåãåºããã¤ã¼ããªå®è£ ã¨ãã¦ã¯ãLMS ã® suffix ãåæãã¦ãè¾æ¸é ã«ã½ã¼ãããã°ããã§ãã
LMS ã® suffix ãåæãããã®ã
2: iissiissiippii$ 6: iissiippii$ 10: iippii$ 16: $
âã½ã¼ã
16: $ 10: iippii$ 6: iissiippii$ 2: iissiissiippii$
ãã® [16, 10, 6, 2] ãæ±ããã種ãã§ããinduced sort ã®ã¹ããã 1 ã§ããã®ã種ããéé ã«èµ°æ»ãã¦ãåãã³ã®æå¾ããè©°ãã¦ããã¨æ¬¡ã®ããã«ãªãã¾ãã
0 $ S : 16 $ 1 i L : -- 2 i L : -- 3 i S : -- 4 i S : -- 5 i S : -- 6 i S : 10 iippii$ 7 i S : 6 iissiippii$ 8 i S : 2 iissiissiippii$ 9 m L : -- 10 m L : -- 11 p L : -- 12 p L : -- 13 p L : -- 14 p L : -- 15 s L : -- 16 s L : --
ãã®ç¶æ ã§ã¹ããã 2 㨠3 ãå®è¡ããã°ããã§ããæ£ãã suffix array ãå¾ããã¾ãã
ãã ããã¤ã¼ããªå®è£ ã§ã¯ O(n) ãéæã§ãã¾ãããããã§ããã®ã½ã¼ãã« SA-IS æ³ãå帰çã«ä½¿ãã¨ããã®ããSA-IS æ³ã®èã§ãã
SA-IS æ³ã®å帰
LMS ã® suffix ã®åã SA-IS æ³ã§ã½ã¼ãããããã«ãsuffix ã®æååä½ããç²ããããã®ããã¤ã³ãã§ãã
"mmiissiissiippii$" ã LMS é¨åæååï¼LMS ãå°å ¥ããã¨ãã«ã¤ãã§ã«èª¬æãã¦ã¾ããï¼ã§åå²ããã¨ã["iissi", "iissi", "iippii$", "$"] ã«ãªãã¾ã *4 ãããã§ã"iissi" ã "iippii$" ã 1 ã¤ã®ãæåãã¨ã¿ãªãããã®åããæååãã¨èãã¾ããããã¦ããã®ãæååãã®ãã¹ã¦ã® suffix ã並ã¹ã¦ã¿ã¾ãã
0: ["iissi", "iissi", "iippii$", "$"] ( 2: iissiissiippii$) 1: ["iissi", "iippii$", "$"] ( 6: iissiippii$) 2: ["iippii$", "$"] (10: iippii$) 3: ["$"] (16: $)
æå¾ã® "(2: iissiissiippii$)" ã "(16: $)" ã¯ãå suffix ãå ã®æååã®ã©ã® suffix ã«å¯¾å¿ãããã表ãã¦ãã¾ãã
åãæåãã®é åºé¢ä¿ï¼"$" < "iippii$" < "iissi"ï¼ã«æ³¨æãã¤ã¤ããã®ãæååãã® suffix ã®åãã½ã¼ããã¾ãã
3: ["$"] (16: $) 2: ["iippii$", "$"] (10: iippii$) 1: ["iissi", "iippii$", "$"] ( 6: iissiippii$) 0: ["iissi", "iissi", "iippii$", "$"] ( 2: iissiissiippii$)
注ç®ãã¹ãã¯ãå æååã®ã¤ã³ããã¯ã¹ã®åããã§ããã[16, 10, 6, 2] ã¨ããæ£ããã種ããå¾ããã¦ãã¾ãã
ã¨ããã§ãä»ãããªã£ãã½ã¼ãã¯ã"iissi" ãªã©ããæåãã¨ã¿ãªãããæååãã® suffix array ãä½ã£ãã®ã¨åãã§ãããã£ã¦ SA-IS æ³ãå帰çã«é©ç¨ã§ãã¾ããå帰ããã¨å ¨ä½ã§ O(n) ã«ãªããªããªãããã§ããããæååãã®é·ãã¯å ã®æååã®é·ãã«æ¯ã¹ã¦ååæªæºã«ãªã£ã¦ãã®ã§ãO(n + n/2 + n/4 + ...) = O(2n) = O(n) ã¨ãããã¨ã§ãç·å½¢æéãä¿ããã¾ãããããã
ã¡ãªã¿ã«ããã®ã¢ã«ã´ãªãºã æ§æææ³ãå帰æ¸éï¼recursive slowdownï¼ã¨ããã¾ããä½è«ã§ããããããé 延è©ä¾¡ã§ãã£ãæé»çå帰æ¸éï¼implicit recursive slowdownï¼ã¨ããææ³ãããã¾ããããããã®ãé¢ç½ããªã¨æã£ã人ã¯ã次ã®æ¬ãã¨ã¦ãé¢ç½ãããããã¾ããã
ãæåãã«çªå·ãæ¯ã
ãã¦ã"iissi" ã "iippii$" ã 1 ã¤ã®ãæåãã¨ãã¦æ±ãã¨è¨ãã¾ããããå®éã«ããããé¨åæååãåãåºãã¨ãæ¯è¼ã« O(n) ããã£ã¦ãã¾ãã®ã§ãã¡ã§ããããã§ã次ã®ããã«çªå·ãæ¯ããã¨ãèãã¾ãã
"$" => 0 "iippii$" => 1 "iissi" => 2
ãã®çªå·ä»ãã¯ã"$" < "iippii$" < "iissi" ã¨ããé åºé¢ä¿ãç¶æãã¦ãã¾ããããã¦ãçªå·å士ãªãæ¯è¼ã O(1) ã§ã§ãã¾ãããã£ã¦ãçªå·ã§ç½®ãæãã¦ãã SA-IS æ³ãå帰ããã° OK ã§ãã
ãã ããã®çªå·ãæ¯ãæ¹æ³ã¯èªæã§ã¯ããã¾ãããä¸æããããçªå·ãæ¯ãããã« O(n^2) ã¨ãããã£ã¦ãã¾ãã¾ãã
ãã®çªå·ä»ãã®ããã«ã1 åç®ã® induced sort ã®ï¼ééã£ãï¼çµæã使ãã¾ããåæ²ã
0 $ S : 16 $ 1 i L : 15 i$ 2 i L : 14 ii$ 3 i S : 10 iippii$ 4 i S : 2 iissi... 5 i S : 6 iissi... 6 i S : 11 ippii$ 7 i S : 3 issi... 8 i S : 7 issi... 9 m L : 1 mi... 10 m L : 0 mmi... 11 p L : 13 pii$ 12 p L : 12 ppii$ 13 s L : 5 si... 14 s L : 9 si... 15 s L : 4 ssi... 16 s L : 8 ssi...
ãããããLMS ã® suffix ã ããåãåºãã¦ã¿ã¾ãã
0 $ S : 16 $ 3 i S : 10 iippii$ 4 i S : 2 iissi... 5 i S : 6 iissi...
... ãé¤ãã¨ãLMS é¨åæååã°ããåºã¦ãã¾ãããããã¯å¶ç¶ã§ã¯ããã¾ãããçç±â*5
ãã£ã¦ããã®æ å ±ãæ´»ç¨ãããã¨ã§ããã£ãã®ãããªçªå·ä»ããå®ç¾ã§ãã¾ããé£ãåã LMS é¨åæååãæ¯ã¹ã¦ãç°ãªãå ´åã¯å¥ã®çªå·ããåãå ´åã¯åãçªå·ãé ã«æ¯ã£ã¦ããã° OK ã§ããå ·ä½çã«ã¯æ¬¡ã®ãããªæãã
- "$" ã«çªå· 0 ãæ¯ã£ã¦ãã
- "$" 㨠"iippii$" ã¯ç°ãªãã®ã§ã"iippii$" ã«çªå· 1 ãæ¯ã
- "iippii$" 㨠"iissi" ã¯ç°ãªãã®ã§ã"iissi" ã«çªå· 2 ãæ¯ã
- "iissi" 㨠"iissi" ã¯åããªã®ã§ãæ°ããçªå·ã¯æ¯ããªã
ããã§ææã®çªå·ä»ããã§ãã¾ãããã¡ãªã¿ã«ããã®ã¨ã㯠LMS é¨åæååãç´æ¥æ¯è¼ãã¾ãããæåã®æ¯è¼åæ°ã®åè¨ã O(n) ãªã®ã§ãåé¡ããã¾ããã
å®è£
å®éã«ã»ããã®ã¯ãåãªãçªå·ä»ãã§ã¯ãªãã["iissi", "iissi", "iippii$", "$"] ã®å LMS é¨åæååãçªå·ã§ç½®ãæãããã®ãã¤ã¾ã [2, 2, 1, 0] ã§ãããããä¸æ°ã«æ±ãã¾ãã
# induced sort ã®çµæãã LMS ã® suffix ã ãåãåºã sa = sa.select {|i| lms?(t, i) } # LMS ã®ã¤ã³ããã¯ã¹ i ã«å¯¾ãã¦çªå· nums[i] ãæ¯ã nums = [] # sa[0] ã® LMS 㯠$ ã¨æ±ºã¾ã£ã¦ããã®ã§ãçªå· 0 ãæ¯ã£ã¦ãã nums[sa[0]] = num = 0 # é£ãåã LMS ãæ¯ã¹ã sa.each_cons(2) do |i, j| diff = false # é£ãåã LMS é¨åæååã®æ¯è¼ s.size.times do |d| if s[i + d] != s[j + d] || lms?(t, i + d) != lms?(t, j + d) # LMS é¨åæååã®ç¯å²ã§ç°ãªãæåããã£ã diff = true break elsif d > 0 && (lms?(t, i + d) || lms?(t, j + d)) # LMS é¨åæååã®çµç«¯ã«è³ã£ã break end end # é£ãåã LMS é¨åæååãç°ãªãå ´åã¯ãçªå·ãå¢ãã num += 1 if diff # LMS ã®ã¤ã³ããã¯ã¹ j ã«çªå· num ãæ¯ã nums[j] = num end # nums ã®ä¸ã«åºç¾ããçªå·ã®ã¿ã並ã¹ãã¨ãLMS é¨åæååãçªå·ã«ç½®ãæããåãå¾ããã nums = nums.compact
sa.each_cons(2) ã®ä¸ã§ sa.size.times ã使ã£ã¦ããã®ã§ãä¸ç¬ O(n^2) ã®äºéã«ã¼ãã®ããã«ãè¦ãã¾ãããããèããã¨ã«ã¼ãã®å®è¡åæ°ã¯æ大ã§ãå ã®æååå ¨ä½ã 1 åèµ°æ»ããã®ã¨åããªã®ã§ãO(n) ã«åã¾ãã¾ãã
ãã¦ãããã§å¾ããã nums ã« SA-IS æ³ãå帰é©ç¨ãã¾ãããã ãããé£ãåã LMS é¨åæååãå ¨é¨ç°ãªããã®ã ã£ãå ´åãã¤ã¾ãçªå·ã®éè¤ããªãå ´åã¯ããã¡ãã¡å帰ããã¾ã§ããªãããã³ã½ã¼ãï¼åãã³ã®ãµã¤ãºã¯ 1ï¼ã®èãæ¹ã§ suffix array ãç´æ¥æ±ãããã¨ãã§ãã¾ãã
if num + 1 < nums.size # çªå·ã®éè¤ãããã®ã§å帰 sa = sa_is(nums, num + 1) else # çªå·ã®éè¤ããªãå ´åãsuffix array ã容æã«æ±ãããã sa = [] nums.each_with_index {|ch, i| sa[ch] = i } end
ããã¦ãããã§å¾ããã sa ã¯ä¸è¨ã§è¨ã [3, 2, 1, 0] ã«ç¸å½ããæ°åãªã®ã§ãããã LMS ã¤ã³ããã¯ã¹ã®å [16, 10, 6, 2] ã«å¤æãã¾ãã
lmss = (0...s.size).select {|i| lms?(t, i) }
seed = sa.map {|i| lmss[i] }
ããã¦ããã®ã種ããå ã« induced sort ãå度è¡ãã°ãã¤ãã«å®äºã§ããé·ãã£ãã
ã¾ã¨ã
suffix array ã O(n) ã§ä½ãã¢ã«ã´ãªãºã SA-IS æ³ã説æãã¾ããã
ä¸ã«ãã解説ãèªåã«ã¯ãã¾ãã¡ãããã«ãããã®ããè¦ã¤ãããªãã£ãã®ã§æ¸ãã¦ã¿ã¾ãããããã£ã±ããããä»ã®äººã«ã¨ã£ã¦ã¯ãããã«ãããã®ã«ãªã£ã¦ããã®ããããã¾ãããã³ã¡ã³ããããããæ¹è¯ãèãã¾ãã
ãã¾ãï¼ããã°ã©ã å ¨ä½
# ã¤ã³ããã¯ã¹ i ã LMS ãã©ãã def lms?(t, i) i > 0 && t[i - 1] == :L && t[i] == :S end def induced_sort(s, k, t, lmss) # ä½æ¥é å sa = [nil] * s.size # s ã«åºç¾ããæå種ãã¨ã®ã«ã¦ã³ã bin = [0] * (k + 1) s.each {|ch| bin[ch + 1] += 1 } # æå種ãç´¯ç©ãããã¨ã§ bin ã®ã¤ã³ããã¯ã¹ã決ãã sum = 0 bin = bin.map {|v| sum += v } # ã¹ããã 1: LMS ã®ã¤ã³ããã¯ã¹ããã³ã®çµããã®æ¹ããå ¥ãã count = [0] * k # ãã³ãã¨ã«ãã§ã«æ¿å ¥ããæ°ãã«ã¦ã³ããã lmss.reverse_each do |i| ch = s[i] # ch ãå ¥ãããã³ã®çµãã (bin[ch + 1] - 1) ããè©°ãã¦ããã sa[bin[ch + 1] - 1 - count[ch]] = i count[ch] += 1 end # ã¹ããã 2: sa ãæé ã«èµ°æ»ãã¦ãã count = [0] * k # ãã³ãã¨ã«ãã§ã«æ¿å ¥ããæ°ãã«ã¦ã³ããã sa.each do |i| next if i == nil next if i == 0 next if t[i - 1] == :S # sa ã«å ¥ã£ã¦ããã¤ã³ããã¯ã¹ i ã«ã¤ãã¦ãi - 1 ã L åã§ããã¨ãã # æå s[i - 1] ã«å¯¾å¿ãããã³ã« i - 1 ãé ããè©°ãã¦ããã ch = s[i - 1] sa[bin[ch] + count[ch]] = i - 1 count[ch] += 1 end # ã¹ããã 3: sa ãéé ã«èµ°æ»ãã¦ãã count = [0] * k # ãã³ãã¨ã«ãã§ã«æ¿å ¥ããæ°ãã«ã¦ã³ããã sa.reverse_each do |i| next if i == nil next if i == 0 next if t[i - 1] == :L # sa ã«å ¥ã£ã¦ããã¤ã³ããã¯ã¹ i ã«ã¤ãã¦ãi - 1 ã S åã§ããã¨ãã # æå s[i - 1] ã«å¯¾å¿ãããã³ã« i - 1 ãçµããããè©°ãã¦ããã ch = s[i - 1] sa[bin[ch + 1] - 1 - count[ch]] = i - 1 # ä¸æ¸ããããã¨ããã count[ch] += 1 end sa end def sa_is(s, k) # L åã S åãã®ãã¼ãã« t = [nil] * s.size # æå¾ã¯ S t[-1] = :S (s.size - 2).downto(0) do |i| # s[i] < s[i+1] ãªãæããã« s[i..] < s[i+1..] => i 㯠S å # s[i] > s[i+1] ãªãæããã« s[i..] > s[i+1..] => i 㯠L å # s[i] == s[i+1] ã®å ´åãs[i..] <=> s[i+1..] ã®æ¯è¼çµæ㯠# s[i+1..] <=> s[i+2..] ã«æºãã (ã¤ã¾ã t[i + 1] ã¨åã) case when s[i] < s[i + 1] then t[i] = :S when s[i] > s[i + 1] then t[i] = :L else t[i] = t[i + 1] end end # LMS ã®ã¤ã³ããã¯ã¹ã ããéããé å lmss = (0...s.size).select {|i| lms?(t, i) } # é©å½ãªã種ãï¼seed = lmss.shuffle ã§ããã seed = lmss # 1 åç®ã® induced sort sa = induced_sort(s, k, t, seed) # induced sort ã®çµæãã LMS ã® suffix ã ãåãåºã sa = sa.select {|i| lms?(t, i) } # LMS ã®ã¤ã³ããã¯ã¹ i ã«å¯¾ãã¦çªå· nums[i] ãæ¯ã nums = [] # sa[0] ã® LMS 㯠$ ã¨æ±ºã¾ã£ã¦ããã®ã§ãçªå· 0 ãæ¯ã£ã¦ãã nums[sa[0]] = num = 0 # é£ãåã LMS ãæ¯ã¹ã sa.each_cons(2) do |i, j| diff = false # é£ãåã LMS é¨åæååã®æ¯è¼ s.size.times do |d| if s[i + d] != s[j + d] || lms?(t, i + d) != lms?(t, j + d) # LMS é¨åæååã®ç¯å²ã§ç°ãªãæåããã£ã diff = true break elsif d > 0 && (lms?(t, i + d) || lms?(t, j + d)) # LMS é¨åæååã®çµç«¯ã«è³ã£ã break end end # é£ãåã LMS é¨åæååãç°ãªãå ´åã¯ãçªå·ãå¢ãã num += 1 if diff # LMS ã®ã¤ã³ããã¯ã¹ j ã«çªå· num ãæ¯ã nums[j] = num end # nums ã®ä¸ã«åºç¾ããçªå·ã®ã¿ã並ã¹ãã¨ãLMS é¨åæååãçªå·ã«ç½®ãæããåãå¾ããã nums = nums.compact if num + 1 < nums.size # çªå·ã®éè¤ãããã®ã§å帰 sa = sa_is(nums, num + 1) else # çªå·ã®éè¤ããªãå ´åãsuffix array ã容æã«æ±ãããã sa = [] nums.each_with_index {|ch, i| sa[ch] = i } end # æ£ããã種ã seed = sa.map {|i| lmss[i] } # 2 åç®ã® induced sort sa = induced_sort(s, k, t, seed) sa end # é¡æã®æåå s = "mmiissiissiippii".bytes + [0] k = 256 # æå種ã®æ° p sa_is(s, k)
ãªãããã®ããã°ã©ã 㯠Ruby ããã大å¤å¯è±ªçã«æ¸ããã¦ãã¾ãï¼é åä½ãã¾ããï¼ãå è«æã® C ããã°ã©ã ã¯ããã³ã®ä½ç½®ä»¥å¤ã®é åããã¹ã¦ SA ã¨ãã 1 ã¤ã®é åã®åå©ç¨ã§è§£æ±ºãã¦ãã¦ãã£ãããã§ãã
åºå ¸
- Ge Nong, Sen Zhang, and Wai Hong Chan. Two Efficient Algorithms for Linear Time Suffix Array Construction
追è¨ï¼2018-02-10ï¼ï¼ã³ã¡ã³ãã§ã®ææãåãã¦ãã°ä¿®æ£ããé£ãåã LMS é¨åæååã®æ¯è¼ãã®ã«ã¼ãçµäºæ¡ä»¶ãééã£ã¦ã¾ããã
*1:L åã¯ã1 æåç®ã 2 æåç®ãã Larger ã§ãï¼ä¾ï¼"ba...")ãS åã¯ã1 æåç®ã 2 æåç®ãã Smaller ã§ãï¼ä¾ï¼"bc..."ï¼ãæããã« "ba..." < "bc..." ãªã®ã§ã確ãã« L å㯠S åããåã«æ¥ã¦ã¾ãã1 æåç®ã¨ 2 æåç®ãåãã«ãªã£ã¦ããæååã®å ´åãã¾ãåãããã«è¨¼æã§ãã¾ãã
*2:ã¤ã³ããã¯ã¹ i ã«å¯¾ã㦠i-1 ã L åã®ã¨ãã ãæ¿å ¥ãããL åã®å®ç¾©ãã s[i-1..] > s[i..] ãã¤ã¾ã s[i-1..] ã®æ¿å ¥ä½ç½®ã¯ s[i..] ããå¾ã«ãªãã
*3:ã¤ã³ããã¯ã¹ 10 ã® suffix "i..." ã¯å é 1 æåã«ã¤ãã¦ã½ã¼ãããã¦ãã¾ããä»åã¯ãã¤ã³ããã¯ã¹ 10 ãå ã«ãã¤ã³ããã¯ã¹ 9 ã® suffix "si..." ã sa[15] ã®ä½ç½®ã«æ¿å ¥ããã¾ãããããã«æ³¨ç®ãã¦ã¿ã¾ããããã "si..." ã s[15] ã«å ¥ãããã¨ãééãã ã¨ããããsa[15] ã¯æå s ã®ãã³å ãªã®ã§ã"si..." ãã大ããããã¾ãã¯å°ããæååãå ¥ãã¹ãã ã£ããã¨ã«ãªãã¾ããããä»®ã«ãs[15] ã®ä½ç½®ã«ã¯ "si..." ãã大ããæååï¼ãã¨ãã° "sz..."ï¼ãå ¥ãã¹ãã ã£ãã¨ããã¨ãs[13] ãã s[14] ã¯ãã§ã«åã¾ã£ã¦ãããã¨ããã"si..." ã¯ãã£ããã©ãã«è¡ãã°ããã®ãããããªããã¨ãããã¨ã«ãªãã®ã§çç¾ãs[15] ã®ä½ç½®ã« "si..." ããå°ããæååï¼ãã¨ãã° "sa..."ï¼ãå ¥ãã¹ãã ã£ãã¨ããã¨ãa ã®æåã®ãã³ã®ä¸ã« "a..." ã®ãããªæååããã£ãã¯ãã§ããããã¦ã¹ããã 2 ã§ã¯ä¸ããé çªã«å¦çãã¦ããã®ã§ããã®æååãå ã«å¦çãããsa[15] ã«ã¯ãã§ã« "sa..." ãå ¥ã£ã¦ããã¯ãã§ãããããå®éã«ã¯ sa[15] ã«ããããæååãå ¥ã£ã¦ããªãã£ãã®ã§ãçç¾ãã¨ãããã¨ã§ãã¤ã³ããã¯ã¹ 5 ã® suffix "si..." ãå ¥ãã®ãæ£ããã¨ãããã¨ã«ãªãã¾ãã
*4:å é ã® "mm" 㯠LMS é¨åæååã§ã¯ãªãã®ã§æ¨ã¦ã¾ããã¾ããLMS é¨åæååã®åãç®ã§ 1 æåéè¤ãã¦ã¾ãã
*5:ç¹å®ã® suffix ã«æ³¨ç®ã㦠induced sort ã®åããè¦ã¦ã¿ã¾ããã¹ããã 1 㧠sa[8] (sa ã® 8 çªç®) ã«å ¥ããããã¤ã³ããã¯ã¹ 10 ã«æ³¨ç®ãã¦ã¿ã¾ããããã¹ããã 2 ã§ã¯ãã¤ã³ããã¯ã¹ 10 ãå ã«ãL åã¤ã³ããã¯ã¹ 9 ã s[14] ã«å ¥ãããã¾ããããã®ã¤ã³ããã¯ã¹ 9 ãå ã«ãL åã¤ã³ããã¯ã¹ 8 ã s[16] ã«å ¥ãããã¾ããã次ã®ã¤ã³ããã¯ã¹ 7 㯠S åãªã®ã§ãã¹ããã 2 ã¯ããã§çµããã§ããã¹ããã 3 ã§ã¯ãã¤ã³ããã¯ã¹ 8 ãå ã«ãS åã¤ã³ããã¯ã¹ 7 ã s[8] ã«å ¥ãããã¾ãããã¤ã³ããã¯ã¹ 7 ãå ã«ãS åã¤ã³ããã¯ã¹ 6 ã s[5] ã«å ¥ãããã¾ããã次ã®ã¤ã³ããã¯ã¹ 5 㯠L åãªã®ã§ãã¹ããã 3 ã¯ããã§çµãããè¦ããã«ãLMS ããå§ãã¦ãã®åã® L åãé 次追å ããããã«ãã®åã® S åãé 次追å ãããã¹ã¿ã¼ãã® LMS ããã¿ã¦ 1 ã¤åã® LMS ã«ãã©ãçããæç¹ã§çµäºãã¨ããåãã«ãªã£ã¦ãã¾ããLMS ãã 1 ã¤åã® LMS ã¾ã§ã®ç¯å²ï¼ããªãã¡ LMS é¨åæååï¼ã«ã¤ãã¦ã½ã¼ãããããã¨ãããã¨ã«ãªãã¾ãã