当前位置: 首页 > 面试题库 >

like_text如何工作?

林亦
2023-03-14
问题内容

我刚刚找到了same_text函数,并且一直在使用它,但是输出百分比总是令我惊讶。请参阅下面的示例。

我试图找到有关在php:similar_text()
Docs
上使用的算法的信息:

<?php
$p = 0;
similar_text('aaaaaaaaaa', 'aaaaa', $p);
echo $p . "<hr>";
//66.666666666667
//Since 5 out of 10 chars match, I would expect a 50% match

similar_text('aaaaaaaaaaaaaaaaaaaa', 'aaaaa', $p);
echo $p . "<hr>";
//40
//5 out of 20 > not 25% ?

similar_text('aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa', 'aaaaa', $p);
echo $p . "<hr>"; 
//9.5238095238095 
//5 out of 100 > not 5% ?


//Example from PHP.net
//Why is turning the strings around changing the result?

similar_text('PHP IS GREAT', 'WITH MYSQL', $p);
echo $p . "<hr>"; //27.272727272727

similar_text('WITH MYSQL', 'PHP IS GREAT', $p);
echo $p . "<hr>"; //18.181818181818

?>

谁能解释这是如何工作的?

更新:

多亏了这些评论,我发现该百分比实际上是使用相似字符的数量* 200 /长度1 +长度2计算得出的

Z_DVAL_PP(percent) = sim * 200.0 / (t1_len + t2_len);

因此,这解释了为什么敏锐度高于预期的原因。对于95中有5个的字符串,结果为10,所以我可以使用。

similar_text('aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa', 'aaaaa', $p);
echo $p . "<hr>"; 
//10
//5 out of 95 = 5 * 200 / (5 + 95) = 10

但是我仍然不知道为什么PHP在翻转字符串时会返回不同的结果。dfsq提供的JS代码不会执行此操作。查看PHP中的源代码,我只能在以下几行中找到不同之处,但我不是交流程序员。一些区别的见解,将不胜感激。

在JS中:

for (l = 0;(p + l < firstLength) && (q + l < secondLength) && (first.charAt(p + l) === second.charAt(q + l)); l++);

在PHP中:(php_similar_str函数)

for (l = 0; (p + l < end1) && (q + l < end2) && (p[l] == q[l]); l++);

资源:

/* {{{ proto int similar_text(string str1, string str2 [, float percent])
   Calculates the similarity between two strings */
PHP_FUNCTION(similar_text)
{
  char *t1, *t2;
  zval **percent = NULL;
  int ac = ZEND_NUM_ARGS();
  int sim;
  int t1_len, t2_len;

  if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss|Z", &t1, &t1_len, &t2, &t2_len, &percent) == FAILURE) {
    return;
  }

  if (ac > 2) {
    convert_to_double_ex(percent);
  }

  if (t1_len + t2_len == 0) {
    if (ac > 2) {
      Z_DVAL_PP(percent) = 0;
    }

    RETURN_LONG(0);
  }

  sim = php_similar_char(t1, t1_len, t2, t2_len);

  if (ac > 2) {
    Z_DVAL_PP(percent) = sim * 200.0 / (t1_len + t2_len);
  }

  RETURN_LONG(sim);
}
/* }}} */


/* {{{ php_similar_str
 */
static void php_similar_str(const char *txt1, int len1, const char *txt2, int len2, int *pos1, int *pos2, int *max)
{
  char *p, *q;
  char *end1 = (char *) txt1 + len1;
  char *end2 = (char *) txt2 + len2;
  int l;

  *max = 0;
  for (p = (char *) txt1; p < end1; p++) {
    for (q = (char *) txt2; q < end2; q++) {
      for (l = 0; (p + l < end1) && (q + l < end2) && (p[l] == q[l]); l++);
      if (l > *max) {
        *max = l;
        *pos1 = p - txt1;
        *pos2 = q - txt2;
      }
    }
  }
}
/* }}} */


/* {{{ php_similar_char
 */
static int php_similar_char(const char *txt1, int len1, const char *txt2, int len2)
{
  int sum;
  int pos1, pos2, max;

  php_similar_str(txt1, len1, txt2, len2, &pos1, &pos2, &max);

  if ((sum = max)) {
    if (pos1 && pos2) {
      sum += php_similar_char(txt1, pos1,
                  txt2, pos2);
    }
    if ((pos1 + max < len1) && (pos2 + max < len2)) {
      sum += php_similar_char(txt1 + pos1 + max, len1 - pos1 - max,
                  txt2 + pos2 + max, len2 - pos2 - max);
    }
  }

  return sum;
}
/* }}} */

Javascript中的源代码:与 JavaScript
类似的文本端口


问题答案:

看起来函数确实根据参数顺序使用了不同的逻辑。我认为有两件事在起作用。

首先,请参见以下示例:

echo similar_text('test','wert'); // 1
echo similar_text('wert','test'); // 2

似乎正在测试“在param2中找到param1的任何不同字符的次数”,因此,如果在周围交换参数,结果将有所不同。据报道,它是一个错误,已被关闭为“按预期工作”。

现在,以上对于PHP和javascript实现都是 相同
的-参数表顺序会产生影响,因此说JS代码不会执行此操作是错误的。在Bug条目中认为这是预期的行为。

其次-看起来不正确的是MYSQL /
PHP单词示例。这样,javascript版本给出了3个与参数顺序无关的参数,而PHP提供了2个和3个参数(由于这个原因,百分比也同样不同)。现在,短语“
PHP IS GREAT”和“ WITH
MYSQL”应该共有5个字符,这与您进行比较的方式无关:H,I,S和T,每个字符一个,再加上一个空格。为了使它们具有3个字符,分别为“
H”,“’和’S”,因此,如果您查看顺序,则正确的答案应该是两种方式都为3。我将C代码修改为可运行的版本,并添加了一些输出,因此可以看到那里发生了什么(codepad
link):

#include<stdio.h>

/* {{{ php_similar_str
 */
static void php_similar_str(const char *txt1, int len1, const char *txt2, int len2, int *pos1, int *pos2, int *max)
{
  char *p, *q;
  char *end1 = (char *) txt1 + len1;
  char *end2 = (char *) txt2 + len2;
  int l;

  *max = 0;
  for (p = (char *) txt1; p < end1; p++) {
    for (q = (char *) txt2; q < end2; q++) {
      for (l = 0; (p + l < end1) && (q + l < end2) && (p[l] == q[l]); l++);
      if (l > *max) {
        *max = l;
        *pos1 = p - txt1;
        *pos2 = q - txt2;
      }
    }
  }
}
/* }}} */


/* {{{ php_similar_char
 */
static int php_similar_char(const char *txt1, int len1, const char *txt2, int len2)
{
  int sum;
  int pos1, pos2, max;

  php_similar_str(txt1, len1, txt2, len2, &pos1, &pos2, &max);

  if ((sum = max)) {
    if (pos1 && pos2) {
      printf("txt here %s,%s\n", txt1, txt2);
      sum += php_similar_char(txt1, pos1,
                  txt2, pos2);
    }
    if ((pos1 + max < len1) && (pos2 + max < len2)) {
      printf("txt here %s,%s\n", txt1+ pos1 + max, txt2+ pos2 + max);
      sum += php_similar_char(txt1 + pos1 + max, len1 - pos1 - max,
                  txt2 + pos2 + max, len2 - pos2 - max);
    }
  }

  return sum;
}
/* }}} */
int main(void)
{
    printf("Found %d similar chars\n",
        php_similar_char("PHP IS GREAT", 12, "WITH MYSQL", 10));
    printf("Found %d similar chars\n",
        php_similar_char("WITH MYSQL", 10,"PHP IS GREAT", 12));
    return 0;
}

结果输出:

txt here PHP IS GREAT,WITH MYSQL
txt here P IS GREAT, MYSQL
txt here IS GREAT,MYSQL
txt here IS GREAT,MYSQL
txt here  GREAT,QL
Found 3 similar chars
txt here WITH MYSQL,PHP IS GREAT
txt here TH MYSQL,S GREAT
Found 2 similar chars

因此,可以看到,在第一个比较中,该函数找到了“ H”,“”和“ S”,但没有找到“ T”,并得到了3的结果。第二个比较发现了“ I”和“
T”,但没有找到’H’,’‘或’S’,因此得到2的结果。

从输出中可以看到产生这些结果的原因:算法从第二个字符串包含的第一个字符串中取出第一个字母,对其进行计数, 然后从第二个字符串中丢弃之前的char
。这就是为什么它错过了中间的字符,这就是在更改字符顺序时引起差异的原因。

发生的事情可能是故意的,也可能不是故意的。但是,这不是javascript版本的工作方式。如果您在javascript版本中打印出相同的内容,则会得到以下信息:

txt here: PHP, WIT
txt here: P IS GREAT,  MYSQL
txt here: IS GREAT, MYSQL
txt here: IS, MY
txt here:  GREAT, QL
Found 3 similar chars
txt here: WITH, PHP 
txt here: W, P
txt here: TH MYSQL, S GREAT
Found 3 similar chars

显示javascript版本以不同的方式实现。javascript版本的作用是在第一次比较中发现’H’,’‘和’S’的顺序相同,而在第二次比较中发现相同的’H’,’‘和’S’-因此在这种情况下,参数的顺序无关紧要。

由于javascript旨在复制PHP函数的代码,因此其行为必须相同,因此我根据对@Khez和该修复程序的分析提交了错误报告,该错误报告现已合并。



 类似资料:
  • 问题内容: 我对如何使用动作监听器和实现它们有一个想法,但是我想知道是否有人可以告诉我他们如何监听事件?有某种轮询机制吗? 问题答案: 动作侦听器使用观察者模式注册事件,主事件循环会将它们注册的所有事件通知它们。所以不,这不是轮询(拉)机制,而是相反的(推)回调。这是“不给我们打电话,我们给您打电话”编程的一个例子。因为代码中的所有内容都在单个线程(事件循环)上运行,所以您不必担心不同事件之间的同

  • 问题内容: 我试图了解Collections.binarySearch如何在Java中工作。我不太明白我得到的输出。 此代码的输出为-1。 当按此顺序插入元素时 结果是0。我认为如果找不到该元素,则结果为负数。有人可以澄清我收到的输出吗? 问题答案: 您的数据必须根据给定的比较器进行排序,以使二进制搜索能够按预期工作。(如果不是,则行为是不确定的。) 在进行此调用之前,必须根据指定的比较器(通过方

  • 问题内容: 我正在尝试了解linux syscallsched_setaffinity()的工作方式。这是我在这里提出的问题的后续。 我有本指南,该指南说明了如何使用syscall并有一个非常简洁(工作!)的示例。 因此,我下载了Linux 2.6.27.19 内核源代码。 我对包含该系统调用的行进行了“ grep”操作,得到了91个结果。没有希望。 最终,我试图了解内核如何 为特定内核 (或处理

  • 问题内容: 我刚刚了解到。它用于动态加载扩展的驱动程序。然后我们得到使用方法的连接。 那么整个事情如何运作? DriverManager类如何知道如何在不使用实际驱动程序的类名的情况下获取连接。 我们也可以将Class.forName()用于自定义应用程序…如果通过示例进行解释,我将非常高兴。 问题答案: 只需加载一个类,包括运行其静态初始化程序,如下所示: 您正在谈论的所有其余过程都是特定于JD

  • 问题内容: ArrayList在内部使用什么数据结构? 问题答案: 内部使用。 在向中添加项目时,列表会检查后备阵列是否还有剩余空间。如果有空间,则将新项目添加到下一个空白处。如果没有空间,则会创建一个更大的新阵列,并将旧阵列复制到新阵列中。 现在,还有更多空间,新元素将添加到下一个空白空间。 由于人们真的很喜欢源代码: 直接跳出JDK。

  • 问题内容: 为了清楚起见,我试图找出Collections.sort(list,new MyComp())方法如何按顺序调用compare方法。 我有一个带有雇员及其个人号码(k)的LinkedList:这些号码是:{1,2,3,4,5,6} MyComparator中的compare(Object o1,Object o2)方法返回一些数字(即与该问题无关)。sort()如何比较方法?它使用参数