Nivasch’s cycle detection algorithm

一 简介

1.1 说明

此算法与Floyd和Brent算法一样,都是寻找由函数F(X)产生的序列S中是否存在循环,而且多用在非循环序列比循环序列长的序列中。上面提到的两个算法已经有很多人科普,唯独这个算法没有人科普,我就献丑了。

与前面所提到的两个算法不同,此算法需要维护一个堆栈结构Stack,该栈结构存储着目前序列出现的最小点distinguished points),而这些点很可能会出现在循环里。当然,事关效率与资源问题,这些点不能多也不能少。为了增加效率,Stack中的序列必须有序(递增),才能使用二分查找算法进行比对以减少时间复杂度。

1.2 结论

假设非循环序列长度为s,循环序列为l。

  1. 算法发现碰撞时,相遇点(不是碰撞点)在第一轮循环之后,范围在[s+l,s+2l-1];
  2. 内存消耗很少;
  3. 该算法找碰撞点与计算s和l的大小都比前面提到的两个算法简单且快速。

二 算法描述

2.1 文字描述

  1. 初始化栈S,并将第一个产生的X0以(X0, 0)的形式放到栈里。
  2. 生成Xi,并在S中进行二分搜索,若没有发现Xi则进行3,若发现已存在Xi则进行4。
  3. 将S中值大于Xi的值剔除,并添加(Xi, i)入S,重复2。
  4. 发现已存在点(Xi, j)。发现存在循环,算法结束。

2.2 伪代码

Require: Input initial sequence value X0, max. iterations M
Create empty stack S
Let x ←− X0
Add pair (x, 0) to the stack
for i from 1 to M do
	Let x ←− F(x)Search x by dichotomy in the (sorted) first component
	if (x, j) is found then
		Output ‘Collision between i and j’
		Exit
	else
		We know that Sk < x < Sk+1
		Truncate S after Sk
		Add pair (x, i) at the end of S
	end if
end for
Output Failed

2.3 计算非循环序列长度s以及碰撞点

已发现(Xi, j)存在在S中,则Xi则是S中从左到右第一个在循环里面的点,记录该点a,则只需遍历a~j即可到达碰撞点,得到s。

2.4 计算循环序列长度l

不像上面提到的两个算法,这里的i-j=t,t=l,而不是l的倍数关系!(i为后Xi,j为前面的Xi)

2.5 例子

假设函数F产生的序列为:

1 4 2 5 6 3 6

no.(i)SF(x)是否能在S中找到F(X)
1<(1,0)>4no
2<(1,0),(4,1)>2no
3<(1,0),(2,2)>5no
4<(1,0),(2,2),(5,3)>6no
5<(1,0),(2,2),(5,3),(6,4)>3no
6<(1,0),(2,2),(3,5)>6no
7<(1,0),(2,2),(3,5),(6,6)>3yes

得到:(3,7)与(3,5)相遇,则环的长度l=7-5=2,碰撞点(环开始的地方)在2~5之间。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值