第三十七 n个长为m+1的字符串。 如果某个字符串的最后m 个字符与某个字符串的前m 个字符匹配

有n 个长为m+1 的字符串, 如果某个字符串的最后m 个字符与某个字符串的前m 个字符匹配,则两个字符串可以联接, 问这n 个字符串最多可以连成一个多长的字符串,如果出现循环,则返回错误

http://www.haogongju.net/art/1670380

<?php
 2     #有n个字符串,每个数组长度m+1,如果数组的后m个元素和另一个数组的前m个元素相同,则两个数组可以相连
 3     #求n个数组中连接起来的最长路径是多少,如果遇到环路则报错退出
 4
 5     function longest($a, $m) {
 6         $len = count($a);
 7         #把二维数组$a的每个字符串元素看成一个节点
 8         #建立节点之间的联通关系数组g,g[i][j]代表节点ij之间的最长路径
 9
10         #初始化g,讲可连通的节点值设为1
11         $g = array();
12         for ($i = 0; $i < $len; $i++) {
13             for ($j = 0; $j < $len; $j++) {
14                 $lastm = substr($a[$i], 1);
15                 $firstm = substr($a[$j], 0, $m);
16                 if ($lastm == $firstm) {
17                     $g[$i][$j] = 1;
18                 } else {
19                     $g[$i][$j] = 0;
20                 }
21             }
22         }
23
24         #使用弗洛伊德算法计算最长的路径
25         for ($k = 0; $k < $len; $k++) {
26             for ($i = 0; $i < $len; $i++) {
27                 for ($j= 0; $j < $len; $j++) {
28                     if ($g[$i][$k] > 0 && $g[$k][$j] > 0) {
29                         $dist = $g[$i][$k] + $g[$k][$j];
30                         if ($dist > $g[$i][$j]) {
31                             $g[$i][$j] = $dist;
32                         }
33                     }
34                 }
35             }
36         }
37
38         #检测环路
39         #环路包括两种,一种是i->i自己到自己,另一种是,i->...->k->...->i
40         for ($i = 0; $i < $len; $i++) {
41             if ($g[$i][$i] >= 1) die("There is a circle");
42         }
43
44         #求出最长路径
45         $max = 0;
46         for ($i = 0; $i < $len; $i++) {
47             $max = max(max($g[$i]), $max);
48         }
49
50         return $max;
51     }
52
53     $a = array(
54             "abcd",
55             "bcde",
56             "cdea",
57             "deab",
58             "eaba",
59             "abab",
60             "deac",
61             "cdei",
62             "bcdf",
63             "cdfi",
64             "dfic",
65             "cdfk",
66             "bcdg",
67         );
68
69     print_r(longest($a, 3));
70 ?>

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值