Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/video/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Php 同义词查找算法_Php_Python_Algorithm_Synonym_Data Analysis - Fatal编程技术网

Php 同义词查找算法

Php 同义词查找算法,php,python,algorithm,synonym,data-analysis,Php,Python,Algorithm,Synonym,Data Analysis,我认为这个例子比Looong的描述要好得多:) 假设我们有一个数组: ("Server1", "Server_1", "Main Server", "192.168.0.3") ("Server_1", "VIP Server", "Main Server") ("Server_2", "192.168.0.4") ("192.168.0.3", "192.168.0.5") ("Server_2", "Backup") 每行包含同义词字符串。作为这个数组的处理结果,我想得到: ("Serve

我认为这个例子比Looong的描述要好得多:)

假设我们有一个数组:

("Server1", "Server_1", "Main Server", "192.168.0.3")
("Server_1", "VIP Server", "Main Server")
("Server_2", "192.168.0.4")
("192.168.0.3", "192.168.0.5")
("Server_2", "Backup")
每行包含同义词字符串。作为这个数组的处理结果,我想得到:

("Server1", "Server_1", "Main Server", "192.168.0.3", "VIP Server", "192.168.0.5")
("Server_2", "192.168.0.4", "Backup")
所以我想我需要一种递归算法。编程语言实际上并不重要——我只需要一点帮助就可以大致了解这个想法。我将使用php或python


谢谢大家!

引入整数标记,表示同义词组。在开始时,一个将所有具有不同标记的单词从
1
标记到
N

然后通过你的收藏进行搜索,如果你发现索引为
i
j
的两个单词是同义词,那么用标记为
i
j
的所有单词进行注释,两者的数量较少。在
N
迭代之后,您将得到所有同义词组


这是一个肮脏且效率不高的解决方案,我相信使用union find结构可以获得更高的性能

这个问题可以归结为图论中的一个问题,在图论中,可以找到一个图中所有连接节点的组

解决这个问题的一个有效方法是使用“洪水填充”算法,它本质上是一种递归的呼吸优先搜索。本文描述了泛洪填充算法及其如何应用于解决查找图的连通区域的问题

要了解如何将原始问题转化为图形上的问题,请将每个条目(例如“Server1”、“Server_1”等)设置为图形上的一个节点。当且仅当节点是同义词时,将节点与边连接。如果有足够的内存,矩阵数据结构特别适合跟踪边。否则,像map这样的稀疏数据结构将起作用,特别是因为同义词的数量可能有限

  • 服务器1是节点#0
  • 服务器1是节点1
  • 服务器2是节点2
然后edge[0][1]=edge[1][0]=1,表示节点#0和#1之间存在一条边(这意味着它们是同义词)。而edge[0][2]=edge[2][0]=0,表示Server1和Server_2是同义词

复杂性分析

创建这个数据结构是非常有效的,因为一个带有字符串到节点号映射查找的线性过程就足以将其装箱。如果将字符串到节点号的映射存储在字典中,那么这将是一个O(n logn)步骤


如果整体填充为O(n),则只需访问图中的每个节点一次。因此,所有的算法都是O(n log n)。

编辑:这可能不是解决问题的最有效方法。如果您对最大性能感兴趣(例如,如果您有数百万个值),您可能会对编写更复杂的算法感兴趣


PHP似乎正在工作(至少使用给定示例中的数据):

输出:

Array
(
    [0] => Array
        (
            [0] => Server1
            [1] => Server_1
            [2] => Main Server
            [3] => 192.168.0.3
            [4] => VIP Server
            [6] => 192.168.0.5
        )

    [2] => Array
        (
            [0] => Server_2
            [1] => 192.168.0.4
            [3] => Backup
        )

)

这将产生比PHP示例(Python 3)更低的复杂性:


那么你说的
Server1
192.168.0.5
是同义词吗?是的。因为Server1=192.168.0.3和192.168.0.3=192.168.0.5,而且您也在选择唯一的,对吗?比如
distinct
。这实际上并不重要。始终可以应用数组_unique。我不需要关于这个或那个词作为同义词被提及的频率的信息。此外,一些智能SQL查询也是一个很好的解决方案!不仅是php/python…我的想法是创建一个数据库表,其中包含
列和
类型
保持
服务器1
类型
保持
1
Value
holds
192.168.0.3
Type
1
Value
holds
Server\u 2
Type
holds
192.168.0.4
。然后用C语言进行一些linq查询,我想我们可以对它们进行分组,但我不知道您是否可以使用表或将有多少字符串。您还可以创建一个使用属性
Value
Type
初始化,并使用相同的系统,我的意思是至少我会先尝试一下。但是,可能会有特殊的算法用于此类工作,我只想创建自己的算法。哇,非常感谢!我有主意了。稍后,我将在完整数据转储(200万条记录,除此之外:)上对此进行测试。在我看来,此算法似乎是O(n^3),但比现有的O(n log n)算法慢得多。200万条记录将与此算法有问题。2个for循环本身将导致内部循环运行4*10^12,除非你手边有一台超级计算机,否则已经不实用了。然后你有了array_intersect()函数,每个函数都通过了内部循环行,我不确定它对性能有什么影响。此外,如果性能太差,请查看更复杂的解决方案。这只是我在没有深入了解数据分析的情况下想到的第一件事(啊,有时候我讨厌在工作中不必解决复杂的问题)。是的,你是对的,但它需要测试。数据集应该每月更改一次,并且数据收集至少需要几个小时,所以即使脚本在一小时内完成任务,这也是一个可以接受的结果。是的,这似乎是一个选项。非常感谢。若算法是O(n),并且您必须访问每个节点一次,那个么总体复杂度是O(n^2)。如果您尝试使用图形,则在更合适的地方进行闭包计算。@p4553d:我不明白为什么它是O(n^2)。您访问每个节点一次,就完成了—一旦访问了节点,您就知道它属于哪个子图。关键当然是跳过您已经访问过的节点,洪水填充算法已经做到了这一点。@Himadri:但是您必须为每个单词找到同义词组。洪水填充算法将只查找一个单词的同义词。图形的“断开连接”区域未被发现。@p4553d:是。
Array
(
    [0] => Array
        (
            [0] => Server1
            [1] => Server_1
            [2] => Main Server
            [3] => 192.168.0.3
            [4] => VIP Server
            [6] => 192.168.0.5
        )

    [2] => Array
        (
            [0] => Server_2
            [1] => 192.168.0.4
            [3] => Backup
        )

)
a = [set(("Server1", "Server_1", "Main Server", "192.168.0.3")),
    set(("Server_1", "VIP Server", "Main Server")),
    set(("Server_2", "192.168.0.4")),
    set(("192.168.0.3", "192.168.0.5")),
    set(("Server_2", "Backup"))]

b = {}
c = set()
for s in a:
    full_s = s.copy()
    for d in s:
        if b.get(d):
            full_s.update(b[d])
    for d in full_s:
        b[d] = full_s
    c.add(frozenset(full_s))

for k,v in b.items():
    fsv = frozenset(v)
    if fsv in c:
        print(list(fsv))
        c.remove(fsv)