ОК, понял:
<?php
require_once('query.lib.php');
$db=new database(DB_TYPE,DB_HOST,DB_USER,DB_PASS,DB_MISC);
$qry=new query('set names utf8',$db);
//Base query, this filters out names that are in just one family
$sql='select name, cast(group_concat(family order by family) as char) as famlist, count(*) as num from people group by name having num>0 order by num desc';
$qry=new query($sql,$db);
//$qry->result is something like
/*
Array
(
[name] => Array
(
[0] => cathy
[1] => george
[2] => jack
[3] => john
[4] => jane
[5] => winston
[6] => peter
)
[famlist] => Array
(
[0] => 2,4,5,6,8
[1] => 2,3,4,5,8
[2] => 1,3,5,7,8
[3] => 1,2,3,6,7
[4] => 2,4,7,8
[5] => 1,2,6,8
[6] => 1,3,6
)
[num] => Array
(
[0] => 5
[1] => 5
[2] => 5
[3] => 5
[4] => 4
[5] => 4
[6] => 3
)
)
$qry->rows=7
*/
//Initialize
$names=$qry->result['name'];
$rows=$qry->rows;
$lists=array();
for ($i=0;$i<$rows;$i++) $lists[$i]=explode(',',$qry->result['famlist'][$i]);
//Walk the list and populate pairs - this filters out pairs, that are specific to only one family
$tuples=array();
for ($i=0;$i<$rows;$i++) {
for ($j=$i+1;$j<$rows;$j++) {
$isec=array_intersect($lists[$i],$lists[$j]);
if (sizeof($isec)>1) {
//Every tuple consists of the name-list, the family list, the length and the latest used name
$tuples[]=array($names[$i].'/'.$names[$j],$isec,2,$j);
}
}
}
//Now walk the tuples again rolling forward, until there is nothing left to do
//We do not use a for loop just for style
$i=0;
while ($i<sizeof($tuples)) {
$tuple=$tuples[$i];
//Try to combine this tuple with all later names
for ($j=$tuple[3]+1;$j<$rows;$j++) {
$isec=array_intersect($tuple[1],$lists[$j]);
if (sizeof($isec)>0) $tuples[]=array($tuple[0].'/'.$names[$j],$isec,$tuple[2]+1,$j);
}
$i++;
}
//We have all the tuples, now we just need to extract the info and prepare to sort - some dirty trick here!
$final=array();
while (sizeof($tuples)>0) {
$tuple=array_pop($tuples);
//name list is in $tuple[0]
$list=$tuple[0];
//count is sizeof($tuple[1])
$count=sizeof($tuple[1]);
//length is in $tuple[2]
$final[]=$tuple[2]*$count."\t$count\t$list";
}
//Sorting and output is all that is left
rsort($final);
print_r($final);
?>
Извините, я только что понял, что использую библиотеку запросов, которую я не могу найти здесь, но из комментария вы легко сможете создать массивыкак в разделе «Инициализация».
По сути, я начинаю с пар. Я сохраняю массив семейств, к которым принадлежат все имена в текущем списке имен, а затем пересекаю его со всеми еще не опробованнымиимена.