ãµãã£ãã¯ã¹ããªãŒã®èª¬æã«é²ãåã«ãçšèªãå®çŸ©ããŸãã ã¢ã«ãŽãªãºã ã®å ¥åã¯ãnæås [0]ãs [1]ã...ãs [n-1]ã§æ§æãããæååsã§ãã åæåã¯ãã€ãã§ãã ãã¡ãããããã§èª¬æãããã¹ãŠã¯ããããã2ãã€ãUnicodeæåãDNAã·ãŒã±ã³ã¹ã®2ãããæåãªã©ãä»ã®ã·ãŒã±ã³ã¹ã§ãæ©èœããŸãã ããã«ãs [n-1]ã¯æå0ãšçãããšä»®å®ããŸãããããã¯sã®ä»ã®ã©ãã«ããããŸããã ãã®æåŸã®å¶éã¯ãç©èªãåçŽåããããã ãã®ãã®ã§ãããå®éããããåãé€ãã ãã§ååã§ãã s [i..j] = s [i] s [i + 1] ... s [j]ãšãã圢åŒã®è¡ïŒiãšjã¯æŽæ°ïŒã¯ãéåžžã©ãããéšåæååãšåŒã°ããŸãã s [i..n-1]ãšãã圢åŒã®éšåæååïŒiã¯æŽæ°ïŒã¯ããµãã£ãã¯ã¹ãšåŒã°ããŸãã
ã ãããäž»äººå ¬ã æååsã®æ¥å°ŸèŸããªãŒã¯ãé ç¹ã®æ°ã«ããæå°ããªãŒã§ãããåæ¥å°ŸèŸs [i..n-1]ãã«ãŒãããç¹å®ã®ã·ãŒããžããŸãã¯ãã®éã§èªã¿åããããã«ãåãšããžã«ç©ºã§ãªããµãã¹ããªã³ã°sãããŒã¯ãããŸãã ãã«ãŒããããªãŒããžã®ãã¹ã§èªã¿åãããåè¡ã¯ãµãã£ãã¯ã¹sã§ãã ãã®å®çŸ©ãåŠçããæãç°¡åãªæ¹æ³ã¯ãããšãã°ïŒçŸæç¹ã§ã¯ãposãlenãããã³toã«æ³šæããªãã§ãã ããïŒã§ãã
æ¥å°ŸèŸããªãŒã«ããé ç¹ã¯2n + 1以äžã§ãã ãµãã£ãã¯ã¹ãé£ç¶ããŠæ¿å ¥ããŠããªãŒãæ§ç¯ããå Žåãããã確èªã§ããŸãã次ã®ãµãã£ãã¯ã¹ãæ¿å ¥ãããšãæ°ãããªãŒããšãã®ãªãŒããã¢ã¿ãããããé ç¹ã衚瀺ãããŸãã s [n-1]ã¯ç¹æ®æåã§ãããããæ¥å°ŸèŸããªãŒã«ã¯æ£ç¢ºã«nåã®èããããŸãã é ç¹ã«æŽæ°ã§çªå·ãä»ããŸãã é ç¹vã®ç¶ãããŒ[v]ã«ä¿æããŸãã vãããã¡ã¶ãŒvãŸã§ã®ãšããžã®ã©ãã«ã¯ãæ°å€ã®ãã¢ãšããŠæ ŒçŽãããŸããã©ãã«ã®é·ãlen [v]ãšããã®ã©ãã«ã®çŽåŸã®äœçœ®pos [v]ã¯ãsã«ãããŸãã ã©ãã«ãæååtã®å Žåãt = s [pos [v] -len [v] .. pos [v] -1]ã é ç¹vã«kåã®åããããt 1 ãt 2 ã...ãt kãvããåãŸã§ã®ãšããžäžã®ã©ãã«ã§ãããšããŸãã è¡t 1 ãt 2 ã...ãt kã®æåã®æåã¯ãã¢ããšã«ç°ãªãããšã«æ³šæããŠãã ãããã€ãŸããåvãžã®åç §ã¯[v]ãžã®ãããã«æ ŒçŽã§ãã察å¿ããåå«ã®ã©ãã«ã®æåã®æåã衚瀺ããŸãã ã³ãŒããçãããããããããªããŠã³ã³ãã¯ããªã³ãŒãã ããšèããããã«ãæ§é ãèšè¿°ãããªããžã§ã¯ãæåã®ã¢ãããŒããé¿ããŸãã ãããã£ãŠãæ¥å°ŸèŸããªãŒã¯æ¬¡ã®ããã«è¡šãããŸãïŒposãlenãããã³äžèšã®å³ã«æ³šæãæãããšãã§ããŸãïŒã
int sz; // int pos[0..sz-1], len[0..sz-1], par[0..sz-1]; //par[v] â v std::map<char, int> to[0..sz-1]; //to[v] â v
æåã®éèŠãªããããã£ã¯ããµãã£ãã¯ã¹ããªãŒãOïŒnïŒã¡ã¢ãªãå æããããšã§ãã
ã«ãŒãããé ç¹vãžã®ãã¹ã«æžãããè¡ã¯ãstrïŒvïŒã§ç€ºãããŸãã strïŒvïŒã¯æšè«ã«ã®ã¿äœ¿çšãããã©ãã«ãæ瀺çã«ä¿åãããŸããã
ãµãã£ãã¯ã¹ããªãŒã®äŸ
ãµãã£ãã¯ã¹ããªãŒã«æ £ãããšåæã«ããã®äœ¿çšæ¹æ³ãç解ããããã«ãããã€ãã®äŸãæ€èšããŠãã ããã
sã®éšåæååãæ€çŽ¢ããŸã
ããããæåã«æãæµ®ãã¶ã®ã¯ããµãã£ãã¯ã¹ããªãŒã䜿çšããŠéšåæååãæ€çŽ¢ããããšã§ãã æååuãæååsã®éšåæååã§ããããšã«æ°ä»ãã®ã¯éåžžã«ç°¡åã§ããããã¯ãuãæ¥å°ŸèŸããªãŒã®ã«ãŒãããèªã¿åãããšãã§ããå Žåã®ã¿ã§ãïŒäžéšã®iãšjã«å¯ŸããŠu = s [i..j]ã§ããããããã£ãŠæ¥å°ŸèŸs [i .n-1]ã¯uïŒã§å§ãŸããŸãã
æååsã®ç°ãªãéšåæååã®æ°
åãçç±ã§ãåéšåæååsãæ¥å°ŸèŸããªãŒã®ãã蟺ã®ã©ãã«äžã®ç¹å®ã®äœçœ®ã«å¯Ÿå¿ããããšã確ç«ã§ããŸãã ãããã£ãŠãç°ãªãéšåæååã®æ°ã¯ãã®ãããªäœçœ®ã®æ°ã§ãããã«ãŒããé€ããã¹ãŠã®é ç¹vã®åèšlen [v]ã«çãããªããŸãã
ããŒã¿å§çž®LZ77
äŸã¯ãã£ãšè€éã§ãã LZ77ïŒgoogle LempelãZivïŒãå§çž®ãããšããèãæ¹ã¯ç°¡åã§ã次ã®æ¬äŒŒã³ãŒãã§èª¬æã§ããŸãã
for (int i = 0; i < n; i = j+1) // s[0..n-1] if ( s[i] s[0..i-1]) { j = i, s[i]; // } else { j = max{j d < i , s[i..j] = s[d..d+ji]}; d = 0,1,âŠ,i-1 , s[d..d+ji] = s[i..j]; (j-i+1, id) // } }
ããšãã°ãæååãaababababaaabãã¯ãaïŒ1,1ïŒbïŒ7,2ïŒïŒ3,10ïŒããšããŠãšã³ã³ãŒããããŸãïŒabababaè¡ã®ãéè€ãã«æ³šæããŠãã ããïŒã ãã¡ãããå®è£ ã®è©³çŽ°ã¯å€§ããç°ãªãå¯èœæ§ããããŸãããåºæ¬çãªèãæ¹ã¯å€ãã®å§çž®ã¢ã«ãŽãªãºã ã§äœ¿çšãããŠããŸãã ãµãã£ãã¯ã¹ããªãŒã䜿çšãããšãOïŒnïŒã§åæ§ã®æ¹æ³ã§sãå§çž®ã§ããŸãã ãããè¡ãããã«ãstart [v]ãs [p..p + | strïŒvïŒ| -1] = strïŒvïŒã®æå°pãšçãããªãããã«ãããªãŒã®åé ç¹vããã£ãŒã«ãstart [v]ã§è£å®ããŸãã ïŒvïŒ| strïŒvïŒã®é·ãã§ãã èã®å Žåããã®å€ã¯ç°¡åã«èšç®ã§ããããšã¯æããã§ãã æ®ãã®é ç¹ã«ã€ããŠã¯ãéå§ãã£ãŒã«ãã¯ããªãŒã®1åã®æ·±ãã«ãã£ãŠèšç®ãããŸãã start [v] = min {start [v 1 ]ãstart [v 2 ]ã...ãstart [v k ]}ãv 1 ãv 2 ã...ãv kã¯vã®åã§ãã ããã§ãå§çž®ã¢ã«ãŽãªãºã ã§jã®æ¬¡ã®å€ãèšç®ããã«ã¯ãããªãŒã®çŸåšã®é ç¹vãéå§ãã[v] <i;ã«ãªããŸã§ãã«ãŒãããæåås [i..n-1]ãèªã¿åãã ãã§ååã§ãã dã¯ãæåŸã®ãã®ãããªå€start [v]ã«çãããã®ãéžæã§ããŸãã
ãµãã£ãã¯ã¹ããªãŒã®æ§ç¯
åçŽåãããWeinerã¢ã«ãŽãªãºã ã¯Ukkonenã¢ã«ãŽãªãºã ããã³åŸæ¥ã®Weinerã¢ã«ãŽãªãºã ãããåçŽã§ããã«ãããããããããã§ããªãéèªæã§ãªãã¢ã«ãŽãªãºã ã§ããããããç解ããã«ã¯ããçšåºŠã®åªåãå¿ èŠã§ããããšãäºåã«èŠåããŸãã
äžè¬çãªèšç»ã ãã¬ãã£ãã¯ã¹ãªã³ã¯
ã¢ã«ãŽãªãºã ã¯ç©ºã®ããªãŒããå§ãŸãããµãã£ãã¯ã¹s [n-1..n-1]ãs [n-2..n-1]ã...ãs [0..n-1]ãé çªã«è¿œå ããŸãïŒå¿µã®ãããè°è«äžã®å®è£ ã§ã¯ãextendé¢æ°ã¯ããµãã£ãã¯ã¹ãæçããå§ãŸãé·ãã®æé ã§æ£ç¢ºã«è¿œå ãããå Žåã«ã®ã¿æ£ããæ©èœããããšãã€ãŸããããšãã°ãã³ãŒãïŒforïŒint i = n-3; i> = 0; i--ïŒextend ïŒiïŒããã°ãå«ãïŒïŒ
for (int i = n-1; i >= 0; i--) extend(i); // s[i..n-1]
ãããã£ãŠãã«ãŒãã®kçªç®ã®ç¹°ãè¿ãã§ãæåås [n-k + 1..n-1]ã®æ¥å°ŸèŸããªãŒããããæ¥å°ŸèŸs [nk..n-1]ãããªãŒã«è¿œå ãããŸãã æ°ããæé·ã®ãµãã£ãã¯ã¹ãè¿œå ããã«ã¯ã1ã€ã®æ°ãããªãŒããšãå Žåã«ãã£ãŠã¯å€ããšããžããåå²ããã1ã€ã®æ°ããé ç¹ãæ¿å ¥ããå¿ èŠãããããšã¯æããã§ãã äž»ãªåé¡ã¯ãæ°ããã·ãŒããæ·»ä»ãããããªãŒå ã®äœçœ®ãèŠã€ããããšã§ãã ãã®åé¡ã解決ããããã«ããµãã£ãã¯ã¹ããªãŒã«ãã¬ãã£ãã¯ã¹ãªã³ã¯ãè¿œå ãããŠããŸã ã
åé ç¹vã«å¯ŸããŠããã¬ãã£ãã¯ã¹ãªã³ã¯link [v]-æåãé ç¹çªå·ã«ãããã³ã°ãããããã次ã®ããã«é¢é£ä»ããŸããã·ã³ãã«ã®å Žåããªã³ã¯[v] [a]ã¯ãstrïŒ wïŒ= a strïŒvïŒãããŠãã®å Žåããªã³ã¯[v] [a] = wã ïŒå€å žçãªWeinerã¢ã«ãŽãªãºã ã«ç²ŸéããŠããå Žåããã¬ãã£ãã¯ã¹ãªã³ã¯ã¯ãæ瀺çãªãå€å žçãªãã¬ãã£ãã¯ã¹ãªã³ã¯ã«å¯Ÿå¿ããŠããããšã«æ°ã¥ããŸããããæé»çãªããªã³ã¯ã¯ãŸã£ããå¿ èŠãªãããšãããããŸãããUkkonenã¢ã«ãŽãªãºã ã«ç²ŸéããŠããå Žåã¯ããã¬ãã£ãã¯ã¹ãªã³ã¯ã¯ããµãã£ãã¯ã¹ãªã³ã¯ããšéã«ãªããŸããïŒå³ã§ã¯ããã¬ãã£ãã¯ã¹ãªã³ã¯ã¯èµ€ã§ç€ºãããé·æ¹åœ¢ã«ã¯ãªã³ã¯ã«å¯Ÿå¿ããã·ã³ãã«ãå«ãŸããŠããŸãïŒãããŒé ç¹0ã®æå³ã«ã€ããŠã¯ä»¥äžãåç §ïŒã
ãããã£ãŠãè¿œå ã®æ§é ããããŸãã
std::map<char, int> link[0..sz-1]; //
å®çŸ©ã«ãããåé ç¹ã«ã€ãªãããã¬ãã£ãã¯ã¹ãªã³ã¯ã¯1ã€ã ãã§ããããããªã³ã¯ã¯OïŒnïŒã¡ã¢ãªãå æãããšçµè«ä»ããŸãã
ãŸããããã§çŽ¹ä»ããå®è£ ã®æè¡çãªãã¥ã¢ã³ã¹ã«ã€ããŠèª¬æããŸãã ããªãŒã®ã«ãŒãã¯é ç¹1ã0ã¯ãã¹ãŠã®æåaã«å¯ŸããŠãªã³ã¯[0] [a] = 1ã§ãããããªãããŒé ç¹ã§ãã ããã«ãpar [1] = 0ããã³len [1] = 1ã§ãããããŒã®é ç¹ã«ã¯ç¹å¥ãªã»ãã³ãã£ãã¯ããŒãã¯ãããŸããããããã€ãã®ç¹å¥ãªã±ãŒã¹ãåãæ¹æ³ã§åŠçã§ããŸãã ããã«ã€ããŠã¯ä»¥äžã§è©³ãã説æããŸãããä»ã®ãšããã¯æ³šæãæã£ãŠã¯ãããŸããã æ°ãããµãã£ãã¯ã¹ãæ¿å ¥ããã¢ã«ãŽãªãºã ã®èª¬æã«é²ã¿ãŸãã
ã¢ã«ãŽãªãºã
è£é¡ã iã0ããn-2ãŸã§ã®æ°å€ãšããŸãã æåås [k..n-1]ã®ãµãã£ãã¯ã¹ããªãŒãèããŸããããã§ãk <= iã§ãã wãs [i..n-1]ã«å¯Ÿå¿ããã«ãŒããããªãŒããžã®ãã¹äžã®éã«ãŒãé ç¹ã§ããå Žåãã«ãŒãããs [i + 1..n-1]ã«å¯Ÿå¿ãããªãŒããžã®ãã¹äžã«ã¯ã次ã®ãããªé ç¹vããããŸãã s [i] strïŒvïŒ= strïŒwïŒããã³link [v] [s [i]] = wïŒå³ãåç §ïŒã
ããã蚌æããŸãããã strïŒwïŒ= s [i] tã瀺ããŸãã æ¥å°ŸèŸããªãŒã®å®çŸ©ã«ãããwã¯ãªãŒãã§ããããwã«ã¯å°ãªããšã2ã€ã®åå«ããããŸãã wãèã®å Žåãvã¯æåås [i + 1..n-1]ã«å¯Ÿå¿ããèã§ãã wãèã«ããªãã§ãã ããã 次ã«ã[w] [a]ã1ã€ã®åwã«ã€ãªããã[w] [b]ãå¥ã®åwã«ã€ãªãããããªãããã€ãã®ç°ãªãèšå·aãšbããããŸãã s [i] taãšs [i] tbã¯sã®éšåæååã§ãïŒå°ãªããšã1ã€ã¯äœçœ®iã§å§ãŸããŸããïŒã ãããã£ãŠãtaãštbãéšåæååã§ãããããªãŒå ã«strïŒvïŒ= tãšãªãé ç¹vãååšããå¿ èŠããããŸãã vãs [i + 1..n-1]ã«å¯Ÿå¿ããã·ãŒããžã®ãã¹äžã«ããããã¬ãã£ãã¯ã¹ãªã³ã¯ã®å®çŸ©ã«ããããªã³ã¯[v] [s [i]] = wã§ããããšã¯æããã§ãã
ãããã£ãŠãæåås [i + 1..n-1]ã®ãµãã£ãã¯ã¹ããªãŒããããæåås [i..n-1]ã®ã·ãŒããè¿œå ããããã«å¿ããŠãã¬ãã£ãã¯ã¹ãªã³ã¯ãæŽæ°ãããšããŸãã äžã®åçãã芧ãã ããã s [i + 1..n-1]ã«å¯Ÿå¿ããå€ãã·ãŒãã瀺ããŸãã æ°ããã·ãŒãã®ããããã³ã°ãã€ã³ããã¯é ç¹w 'ã§ããããŸã äœæãããŠããªãå¯èœæ§ããããŸãã wã«ãã£ãŠãw 'ã®ããäžã«ããé ç¹ã瀺ããŸãïŒwãæ¢ã«ããªãŒã«ããå Žåã¯ãw = w'ã§ããã®å Žåã¯æ°ããèãè¿œå ããã ãã§ååã§ãïŒã ç°¡åã«ããããã«ãæåã«wãã«ãŒãã§ãªãå ŽåãèããŸãã è£é¡ã«ããããªã³ã¯[v] [s [i]] = wã«ãªãããã«ãå€ããã¹ããã«ãŒããžã®ãã¹ã«é ç¹vããããŸãã
äºå®1. vããoldãžã®ãã¹ã«ã¯ãv "'ãªã³ã¯[v' '] [s [i]]ãå®çŸ©ãããŠãããããªé ç¹ã¯ãããŸããã ããã©ããããv ''ããã®ãããªããŒã¯ã§ãããšããŸãã 次ã«ãé ç¹ãªã³ã¯[v ''] [s [i]]ã¯w 'ã®ç¥å ã§ãããåæã«wã®åå«ã§ããããŸãïŒãã¬ãã£ãã¯ã¹ãªã³ã¯ã®å®çŸ©ã«ããïŒã ãããããããã³ã°ãã€ã³ãããæãè¿ãããŒã¯ãšããŠwãéžæããŸããïŒ è«äºã
ã¢ã«ãŽãªãºã ã§ã¯ããŸãvãšwãèŠã€ããŸãã åæã«ãvlenå€æ°ã®å€| strïŒvïŒ| +1ãèšç®ãããã¹ã¹ã¿ãã¯ã«æž¡ããããã¹ãŠã®é ç¹ãè¿œå ããŸã-ãããã¯åŒãç¶ã䟿å©ã§ãã ãµã€ã¯ã«ã®æåŸã§ãs [i + vlen]ã¯ãvããoldãžã®ãã¹ã®åå«vãžã®ãšããžã®æåã®æåã«çããããšã«æ³šæããŠãã ããïŒäžã®å³ãåç §ïŒã
int v, vlen = n - i, old = sz â 1;// old â for (v = old; !link[v].count(s[i]); v = par[v]) { vlen -= len[v]; path.push(v); } int w = link[v][s[i]];
äºå®2. to [w] [s [i + vlen]]ãå®çŸ©ãããŠããªãå Žåã«éããé ç¹w 'ã¯ããªãŒã«æ¢ã«ååšããŸãã ãã®å Žåãw = w 'ã äžã®å³ãšãã·ã³ãã«s [i + vlen]ã®æå³ã«é¢ããçºèšãå°ãé»æ³ãããšããã®ã¹ããŒãã¡ã³ããæããã«ãªããŸãã
äºå®3. vããå€ããã¹ãžã®ãã¹ã«ã¯ãvããããŸããããšãã°ãwããŸã ååšããŠããªããŠããs [i] strïŒv 'ïŒ= strïŒw'ïŒã§ãã w 'ããªãŒã«ãã§ã«ååšããå Žåãã¹ããŒãã¡ã³ãã¯äºå®2ããã³v' = vããæããã§ãã wããŸã äœæãããŠããªããšããŸãã u = to [w] [s [i + vlen]]ãè¡šããŸãã ã«ãŒãuãæã€ãµãããªãŒããä»»æã®èãéžæããŸãã ãã®èãjã®æ¥å°ŸèŸs [j..n-1]ã«å¯Ÿå¿ãããŸãã ãŸã æ¿å ¥ãããŠããªãæ¥å°ŸèŸs [i..n-1]ãšæ¥å°ŸèŸs [j..n-1]ã¯ããæé»ã®ãé ç¹w 'ã§åå²ããŸãã ãã ããs [j + 1..n-1]ããã³s [i + 1..n-1]ã«å¯Ÿå¿ãããªãŒãã¯ãããªãŒã§æ¢ã«è¡šãããŠãããé ç¹v 'ã§åå²ããŠããŸãã s [i] strïŒv 'ïŒ= strïŒw'ïŒã§ããããšã¯æããã§ããã€ãŸããvã¯vããoldãžã®ãã¹ã«ãããŸãã ãã®æç¹ã§ãäžã®å³ãæåŸã«èŠã䟡å€ããããŸãã ã¢ã«ãŽãªãºã ã®äž»èŠéšåã«é²ã¿ãŸãã
wãèŠã€ãã£ãã®ã§ãã¿ã¹ã¯ã¯æ°ããã·ãŒãã®ãããã³ã°ãã€ã³ããèŠã€ããããšã§ãã å®éãlen [w ']ãšé ç¹v'ãæ¢ããŠããŸãã w = w 'ã®å Žåãã·ãŒããwã«ã¢ã¿ããããå€ãã·ãŒããããã®ã·ãŒããžã®ãã¬ãã£ãã¯ã¹ãªã³ã¯ãæç»ããã ãã§ååã§ãã wïŒ= W 'ã®å Žåã®è€éãªã±ãŒã¹ãã€ãŸã ã·ã³ãã«s [i + vlen]ã«ããwããã®ãšããžããããŸãã åã³u = to [w] [s [i + vlen]]ã瀺ããŸãã s [i] strïŒv 'ïŒ= strïŒw'ïŒã®ãããªé ç¹v 'ãèŠã€ãããŸã§ããã¹ã¹ã¿ãã¯ããé ç¹ãé çªã«ååŸããŸãã é©åãªããŒã¯ãèŠã€ãã£ãããšãã©ã®ããã«å€æããŸããïŒ v 1 ãv 2 ã...ãv kããv k = v 'ã®ãã¹ã¹ã¿ãã¯ã®æäžéšã®é ç¹ãšããŸãïŒäžå³ãåç §ïŒã v pããoldãžã®ãã¹äžã®åv pã«ç¶ããšããžã®æåã®æåãpã§ç€ºããŸãã 0 = s [i + vlen]ãå®çŸ©ããŸãã tãwããuãŸã§ã®ãšããžäžã®ã©ãã«ãšããã ã·ã³ãã«t [len [v 1 ] + len [v 2 ] + ... + len [v p -1]]ã¯ãtäžã®pã«å¯Ÿå¿ããã·ã³ãã«ãšåŒã°ããŸãã w 'ã¯wããuãžã®ãšããžäžã®æ¥å°ŸèŸs [i..n-1]ã®åå²ç¹ã§ãããããã·ã³ãã«a k㯠täžã®å¯Ÿå¿ããã·ã³ãã«ãšçãããããŸããã äžæ¹ãåãçç±ã§ãåp = 0,1ã...ãk-1ã«å¯ŸããŠãã·ã³ãã«a pã¯täžã®å¯Ÿå¿ããã·ã³ãã«ãšçãããªããŸãã å³é¢ã䜿çšãããšããã®æšè«ãããæ確ã«ãªããŸãã
åŸãããçºèšã¯ãåçŽåãããWeinerã¢ã«ãŽãªãºã ã®äžæ žã§ãã èå³æ·±ãããšã«ããã¹ãŠã®æåã§ã¯ãªãããšããžã®æåã®æåã®ã¿ãtã®å¯Ÿå¿ããæåãšæ¯èŒããã°ååã§ãã æ¬è³ªçã«ãããã¯ç°¡åãªèŠ³å¯ã§ããããã¯ãã¬ã¹ã©ãŠã¢ãŒãšã€ã¿ãªã¢ãŒããæ°ã¥ããããšã§ãããäœããã®çç±ã§èª°ãæ°ä»ããŠããŸããã§ããã vããto wãžã®ãã¬ãã£ãã¯ã¹ãªã³ã¯ãšå€ãã·ãŒãããæ°ããã·ãŒããžã®ãã¬ãã£ãã¯ã¹ãªã³ã¯ãæç»ããããšãå¿ããªãã§ãã ããã ãã®ãããã¢ã«ãŽãªãºã ã¯æ¬¡ã®ããã«æ°ãããµãã£ãã¯ã¹s [i..n-1]ãæ¿å ¥ããŸãã
if (to[w].count(s[i + vlen])) { // w != w' int u = to[w][s[i + vlen]]; //sz â w', //.. w!=w', s[pos[u] - len[u]] == s[i + vlen] for (pos[sz] = pos[u] - len[u]; s[pos[sz]] == s[i + vlen]; pos[sz] += len[v]) { v = path.top(); path.pop(); // v' vlen += len[v]; } w u w'=sz; len[w'] = len[u]-(pos[u]-pos[sz]) link[v][s[i]] = sz; // v' w' w = sz++; // w = w' } // w w' link[old][s[i]] = sz; // old sz sz w; len[sz] = n â (i + vlen) pos[sz++] = n; //pos n
wãã«ãŒãã§ããå Žåãç¹å¥ãªã±ãŒã¹ãæ€èšããå¿ èŠããããŸãã ãã®ç¶æ³ã¯å®å šã«äŒŒãŠããŸãããäžéšã®å€ã¯1ã€ã·ãããããŸãã ãã¡ããããã®ã±ãŒã¹ãåå¥ã«åŠçããããšãå¯èœã§ããããããŒã®é ç¹ã䜿çšããæ¹ãç°¡åã§ãããè¿œå ã®ã³ãŒããèšè¿°ããå¿ èŠã¯ãããŸããã ãã®å Žæã§éèŠãªåœ¹å²ãæãããŠããã®ã¯ããã¹ãŠã®æåaã«ã€ããŠãpar [1] = 0ãlen [1] = 1ãlink [0] [a] = 1ã§ãã ãããã£ãŠãé ç¹vã®æ€çŽ¢ãµã€ã¯ã«ã¯å¿ ãé ç¹0ã§çµäºããå€len [1] = 1ã¯å¿ èŠãªã·ããã1ã€æäŸããŸãã 詳现ãç解ããã®ã¯é£ãããããŸãããããã¯æŒç¿ãšããŠæ®ããŠãããŸãã ããã«é¢ããæ¶ç©ºã®ããŒã¯ã®ç§å¯ã®æå³ãæããã«ãããããšãé¡ã£ãŠããŸãã ãã¹ãŠãçµã¿åãããããšã§ã次ã®ãœãªã¥ãŒã·ã§ã³ãåŸãããŸãã
void attach(int child, int parent, char c, int child_len) // { to[parent][c] = child; len[child] = child_len; par[child] = parent; } void extend(int i) // ; i=n-1,n-2,...,0 { int v, vlen = n - i, old = sz - 1; for (v = old; !link[v].count(s[i]); v = par[v]) { vlen -= len[v]; path.push(v); } // vlen = |str(v)|+1 int w = link[v][s[i]]; if (to[w].count(s[i + vlen])) { // w != w' int u = to[w][s[i + vlen]]; for (pos[sz] = pos[u]-len[u]; s[pos[sz]]==s[i + vlen]; pos[sz] += len[v]) { v = path.top(); path.pop(); // v' vlen += len[v]; } attach(sz, w, s[pos[u] - len[u]], len[u] - (pos[u] - pos[sz])); // w'(=sz) w attach(u, sz, s[pos[sz]], pos[u] - pos[sz]); // u w'(=sz) w = link[v][s[i]] = sz++; // v' w'; w = w' } // w w' link[old][s[i]] = sz; // attach(sz, w, s[i + vlen], n - (i + vlen)); // sz w' pos[sz++] = n; //pos n } void init() { len[1] = 1; pos[1] = -1; par[1] = 0; //, par[1] = 0 len[1] = 1 (!) for (int c = 0; c < 256; c++) link[0][c] = 1;// 0 }
ã¢ã«ãŽãªãºã ã®å®è¡æéã®æšå®
çµè«ãšããŠã説æããæ§é å šäœãOïŒnïŒæäœãå®è¡ããçç±ãç解ããŸãã é ç¹vã®é«ãã¯ãã«ãŒãããvãŸã§ã®ãã¹äžã®é ç¹ã®æ°ã§ãã ã¢ã«ãŽãªãºã ã®ã¹ãããã¯ãããªãŒã«æ°ãããµãã£ãã¯ã¹ãè¿œå ããããšã§ããããšãæãåºãããŠãã ããã içªç®ã®ã¹ãããã§æãé·ãæ¥å°ŸèŸã«å¯Ÿå¿ããé ç¹ã®é«ããh iã§ç€ºããŸãã k iããã¹ãããiã§oldããvã«ç§»åããé ç¹ã®æ°ãšããŸãã h iã®å€ã¯ã©ã®ããã«å€åããŸããïŒ è£é¡ã®å³ãããäžåºŠèŠããšãåå°æã«h i <h i-1 -k i-1 + 2ã§ããããšãããããŸããiçªç®ã®ã¹ãããã§å®è¡ãããæäœã®æ°ã¯k iã«æ¯äŸããŸãã圌ããæ°ã¥ããããšãOïŒh i + 1 -h i + 2ïŒã ãã®ããšãããã¢ã«ãŽãªãºã ãåèšã§OïŒ2n +ïŒh 1 -h 2 ïŒ+ïŒh 2 -h 3 ïŒ+ ... +ïŒh n-1 -h n ïŒïŒ= OïŒnïŒæäœãå®è¡ããããšã¯æããã§ãã
å°ããªæé©åã®ã¡ã¢ã ããããžã®ã¢ã¯ã»ã¹æéãèãããšãWeinerã¢ã«ãŽãªãºã ïŒããã³UkkonenïŒã®æéã¯OïŒn log mïŒã§ããããã§ãmã¯ã¹ããªã³ã°å ã®ç°ãªãæåã®æ°ã§ãã ã¢ã«ãã¡ããããéåžžã«å°ããå Žåã¯ããããã®ä»£ããã«é åã䜿çšããŠãWeinerãçã«ç·åœ¢ã«ããããšããå§ãããŸãã
å ¬å¹³ã«èšããšãç°¡ç¥åãããWeinerã¢ã«ãŽãªãºã ïŒããã³å€å žçãªã¢ã«ãŽãªãºã ãªã©ïŒãUkkonenãããçŽ1.5åãã2åã®ã¡ã¢ãªãæ¶è²»ããããšã¯æ³šç®ã«å€ããŸãã ãã¹ãã§ã¯ãåçŽåãããWeinerã®åäœãçŽ1.2åé ãããšã瀺ãããŸããïŒããã§ã¯ãUkkonenãããããã«å£ã£ãŠããŸãïŒã ããã«ããããããããããã®æ¬ ç¹ã¯ãã¹ãŠãWeinerã®å®è£ ã®å®¹æããšå€æ°ã®èœãšãç©Žã®æ¬ åŠã«ãã£ãŠéšåçã«çžæ®ºãããŠããŸãã
æç³»åã®ãªã³ã¯
P.ã¯ã€ããŒã ãç·åœ¢ãã¿ãŒã³ãããã³ã°ã¢ã«ãŽãªãºã ã1973ã¯ãWeinerã®æåã®èšäºã§ãæ¥å°ŸèŸããªãŒã玹ä»ããç·åœ¢ã¢ã«ãŽãªãºã ã瀺ããŠããŸãã
E.ãã¯ã¬ã€ãã ãã¹ããŒã¹ç¯çŽåãµãã£ãã¯ã¹ããªãŒæ§ç¯ã¢ã«ãŽãªãºã ã1976ã¯ããã軜éãªãµãã£ãã¯ã¹ããªãŒæ§ç¯ã¢ã«ãŽãªãºã ã§ãã
E.ãã£ãããã ãæ¥å°ŸèŸããªãŒã®ãªã³ã©ã€ã³æ§ç¯ã1995-McCrateã¢ã«ãŽãªãºã ã®ä¿®æ£ã æã人æ°ã®ããææ°ã®ã¢ã«ãŽãªãºã ã
D.ãã¬ã¹ã©ãŠã¢ãŒãGãã€ã¿ãªã¢ãŒãã ãããªã³ãžããŒã¯ãããç¥å åé¡ã«ãããªã¢ã«ã¿ã€ã ã®ãµãã£ãã¯ã¹ããªãŒã®æ§ç¯ã2013ïŒ2011幎ã®æ«å®çïŒ-ãã®èšäºã®ç°¡ç¥åãããWeinerã¢ã«ãŽãªãºã ã®èª¬æã¯1段èœïŒ10ããŒãžã®æ³šéïŒã§ãããä»ã®ãã¹ãŠã¯å¥ã®é¢é£ããåé¡ã«åœãŠãããŠããŸãã
PSã¢ã«ãŽãªãºã ã®ãã¹ããšã³ãŒãæ¹åã®ææ¡ã«ååããŠãããMisha RubinchikãšOleg Merkuryevã«æè¬ããŸãã
PPSçµè«ãšããŠãç§ã¯åŒçšããŸã
ã·ã³ãã«ã§å®å
šãªå®è£
// , "" . // ( ). #include <string> #include <map> const int MAXLEN = 600000; std::string s; int pos[MAXLEN], len[MAXLEN], par[MAXLEN]; std::map<char,int> to[MAXLEN], link[MAXLEN]; int sz = 2; int path[MAXLEN]; void attach(int child, int parent, char c, int child_len) { to[parent][c] = child; len[child] = child_len; par[child] = parent; } void extend(int i) { int v, vlen = s.size() - i, old = sz - 1, pstk = 0; for (v = old; !link[v].count(s[i]); v = par[v]) { vlen -= len[v]; path[pstk++] = v; } int w = link[v][s[i]]; if (to[w].count(s[i + vlen])) { int u = to[w][s[i + vlen]]; for (pos[sz] = pos[u] - len[u]; s[pos[sz]] == s[i + vlen]; pos[sz] += len[v]) { v = path[--pstk]; vlen += len[v]; } attach(sz, w, s[pos[u] - len[u]], len[u] - (pos[u] - pos[sz])); attach(u, sz, s[pos[sz]], pos[u] - pos[sz]); w = link[v][s[i]] = sz++; } link[old][s[i]] = sz; attach(sz, w, s[i + vlen], s.size() - (i + vlen)); pos[sz++] = s.size(); } int main() { len[1] = 1; pos[1] = 0; par[1] = 0; for (int c = 0; c < 256; c++) link[0][c] = 1; s = "abababasdsdfasdf"; for (int i = s.size() - 1; i >= 0; i--) extend(i); }