我正在努力(为了好玩)编写一个可以识别回文的脚本。到目前为止,我成功地使用了“皮划艇”,“赛车”,“安娜”,“一个男人计划运河巴拿马”:然而后一个短语的变体如“amanaplana canalpan ama”给了我一些问题。
作为旁注:我确实理解使用PCRE会让事情变得更容易,但我不能流利,我的主要目标之一是了解背后的算法检查回文。
<?php
$word = "amanaplana canalpan ama";
$space = " ";
$word_smallcase = strtolower($word);
$word_array = str_split($word_smallcase);
if(in_array($space, $word_array)){
for($m = 0; $m<count($word_array); $m = $m + 1){
if($word_array[$m] == $space)
unset($word_array[$m]);
}
}
$count = 0;
$scan_count = -1;
for($i = 0; $i < (count($word_array)/2); $i = $i + 1){
for($j = count($word_array); $j > (count($word_array)/2); $j = $j - 1){
if($word_array[$i]==$word_array[$j]){
$count = $count + 1;
break;
}
}
$scan_count = $scan_count + 1;
}
if ($count == $scan_count){
echo $word." is a palindrome";
}
else{
echo $word ." is NOT a palindrome";
}
?>
我很感激有关的回复:
提前致谢。
答案 0 :(得分:3)
目前,您正在逐字逐句地进行测试,这肯定会导致在回文中字词不均匀的情况下出现错误。
在PHP中查看字符串是否是palandromic的简单方法:
$test = str_replace( array(',', '.', ' '
//, and any other punctuation you aren't using
), '', $input );
$test = strtolower( $test );
echo $input . ' is ' .
( ( strrev( $test ) == $test )? "": "not " )
' palandromic.';
关于你的代码:迭代数组并同时删除东西是一个麻烦的邀请。你最好只使用str_replace。如果那不是一个选项,我会使用:
// this takes more space, but it is easier to understand.
$tmp = array();
for($m = 0; $m<count($word_array); $m++){ // ++ is the same as $m = $m + 1
if($word_array[$m] != $space)
$tmp[] = $word_array[$m];
}
$word_array = $tmp;
如果没有strrev(反转字符串):
$l = count( $word_array ) / 2; // cache this, no sense in recounting
$is_palindromic = TRUE;
for( $i = 0; $i < $l; $i++ )
{
if( $word_array[ $i ] != $word_array[ ( -1 - $i ) ] )
{
$is_palindromic = FALSE;
break;
}
}
echo $input . ' is ' .
( $is_palindromic )? "": "not " )
' palandromic.';
答案 1 :(得分:2)
这里有一些事情......
首先,我不确定你是否知道unset
数组实际上并没有删除索引:
$array = array(0, 1, 2, 3);
unset($array[2]);
var_dump($array);
/* array(3) {
[0]=>
int(0)
[1]=>
int(1)
[3]=>
int(3)
} */
因此,当您遍历数组中的元素时,您将会有一些未定义的偏移量。要逐个使用,您应该使用foreach
循环控件。
另一个问题在于嵌套for循环:
for($i = 0; $i < (count($word_array)/2); $i = $i + 1){
for($j = count($word_array); $j > (count($word_array)/2); $j = $j - 1){
鉴于“amanaplanacanalpanama”,看看你在做什么:
逐步比较(顺便说一下,你在$ j的初始值设定项上是1; $word_array[count($word_array)]
指向巴拿马的'm'而不是'a'。):< / p>
a eq to a? j is 22 i is 0
scan_count: -1 count: 1
m eq to a? j is 22 i is 1
m eq to m? j is 21 i is 1
scan_count: 0 count: 2
a eq to a? j is 22 i is 2
scan_count: 1 count: 3
a eq to a
很好,匹配...... m在下一次迭代中找到,但是当你到达下一个'a'时,你会发现巴拿马末尾的原始'a'。 ..
作为旁注,由于你每次都是从最后开始的,所以考虑到一个足够大的字符串,它会非常低效O(n^2)
...
强制性解决方案:
$word = "amanaplana canalpan ama";
$j = strlen ($word)-1;
$pal = true;
for ($i = 0; $i < strlen($word)/2; ++$i, --$j) {
// skip spaces
while ($word[$i] === " ") {$i++;}
while ($word[$j] === " ") {$j--;}
echo "$word[$i] eq $word[$j]?\n";
if ($word[$i] !== $word[$j]) {
$pal = false;
break;
}
}
if ($pal) print "yes"; else print "no";
答案 2 :(得分:1)
伪代码:
string phrase = "my phrase here"
int i = 0
int j = phrase.length - 1
while i < j:
if phrase[i] is not alphanumeric:
i++;
continue;
if phrase[j] is not alphanumeric:
j--;
continue;
if phrase[i] != phrase[j]
return false;
i++;
j--;
return true
答案 3 :(得分:0)
我认为可以删除所有空格并完全忽略单词。如果字符串长度为奇数,则分成两部分(或左右),反转任意一半,然后查看它们是否匹配。
$word = "amanaplana canalpan ama";
$sanitizedWord = preg_replace("'\s+'", '', strtolower($word));
$halfway = strlen($sanitizedWord)/2;
$roundedDownMidPoint = floor($halfway);
$firstHalf = substr($sanitizedWord, 0, $roundedDownMidPoint);
$secondHalf = substr($sanitizedWord, is_float($halfway) ? $roundedDownMidPoint+1 : $halfway);
if ($firstHalf === strrev($secondHalf)) {
echo $sanitizedWord." is a palindrome";
}
使用“Kayak”,“Racecar”,“Anna”,“A a a plan a canal a Panama”和“amanaplana canalpan ama”进行测试,这些都被正确识别为回文。
答案 4 :(得分:0)
<?php
$a="amanaplana canalpan ama";
echo "String entered: " . $a;
$b= preg_replace('/\s+/', '', $a);
$org= strtolower($b);
$chk= strrev($org);
echo "<br/>";
if ($org==$chk)
{ echo "Palindrome"; }
else
{ echo "Not Palindrome"; }
?>