1 <?php 2 #串连珠子问题(类似于关键字搜索) 3 4 function shortest_sub($a, $m) { 5 $color = array(); #用于存储当前子串某种颜色出现的次数,如color[0] = 2表示颜色0出现2次 6 $sum = 0; #用于存储当前子串共出现了几种颜色 7 $bstart = 0; #最短字串的开始坐标 8 $blen = count($a); #最短子串长度 9 10 #将color数组初始化为0 11 for ($i = 1; $i <= $m; $i++) { 12 $color[$i] = 0; 13 } 14 15 $h = 0; #头指针 16 $t = 0; #尾指针 17 $loop = true; 18 while ($loop) { 19 #统计当前子串颜色出现次数 20 if ($color[$a[$t]] == 0) { 21 #新出现的颜色 22 $color[$a[$t]] = 1; 23 $sum++; 24 } else { 25 $color[$a[$t]]++; 26 } 27 28 #找到了所有颜色,缩减当前子串 29 if ($sum == $m) { 30 $loop2 = true; 31 while ($loop2) { 32 #某种颜色在当前子串(h~t)范围内只出现了一次,说明当前子串已经不能再缩减 33 if ($color[$a[$h]] == 1) { 34 $loop2 = false; 35 36 if ($t < $h) { 37 #如果t跨过了数组尾部又回到数组头 38 $clen = $t + 1 + count($a) - $h; 39 } else { 40 $clen = $t - $h + 1; #当前子串长度 41 } 42 43 #更新最短子串信息 44 if ($clen < $blen) { 45 $blen = $clen; 46 $bstart = $h; 47 } 48 49 $sum--; #减少当前子串出现的颜色总数 50 } 51 52 $color[$a[$h]]--; #减少当前子串的当前颜色出现次数 53 $h++; 54 55 if ($h == count($a)) { #当h扫描到数组尾,扫描结束 56 $loop = false; 57 } 58 } 59 } 60 61 $t++; 62 63 #当t到达数组尾部时,重新回到数组头 64 if ($t == count($a)) $t = 0; 65 } 66 67 return array("start" => $bstart, "len" => $blen); 68 } 69 70 $a = array(4, 5, 5, 1, 2, 3); 71 $t = shortest_sub($a, 5); 72 print_r($t); 73 ?>