激情久久久_欧美视频区_成人av免费_不卡视频一二三区_欧美精品在欧美一区二区少妇_欧美一区二区三区的

服務器之家:專注于服務器技術及軟件下載分享
分類導航

PHP教程|ASP.NET教程|Java教程|ASP教程|編程技術|正則表達式|C/C++|IOS|C#|Swift|Android|VB|R語言|JavaScript|易語言|vb.net|

服務器之家 - 編程語言 - PHP教程 - PHP中實現Bloom Filter算法

PHP中實現Bloom Filter算法

2020-09-15 16:13PHP中文網 PHP教程

這篇文章主要介紹了PHP中實現Bloom Filter算法,本文直接給出實現代碼,代碼中給出詳細注釋,Bloom Filter算法介紹等內容,需要的朋友可以參考下

 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
<?php
 
/*Bloom Filter算法來去重過濾。
 
 
介紹下Bloom Filter的基本處理思路:申請一批空間用于保存0 1信息,再根據一批哈希函數確定元素對應的位置,如果每個哈希函數對應位置的值為全部1,說明此元素存在。相反,如果為0,則要把對應位置的值設置為1。由于不同的元素可能會有相同的哈希值,即同一個位置有可能保存了多個元素的信息,從而導致存在一定的誤判率。
 
如果申請空間太小,隨著元素的增多,1會越來越多,各個元素沖突的機會越來越來大,導致誤判率會越來越大。另外哈希函數的選擇及個數上也要平衡好,多個哈希函數雖然可以提供判斷的準確性,但是會降低程序的處理速度,而哈希函數的增加又要求有更多的空間來存儲位置信息。
 
Bloom-Filter的應用。
  Bloom-Filter一般用于在大數據量的集合中判定某元素是否存在。例如郵件服務器中的垃圾郵件過濾器。在搜索引擎領域,Bloom-Filter最常用于網絡蜘蛛(Spider)的URL過濾,網絡蜘蛛通常有一個 URL列表,保存著將要下載和已經下載的網頁的URL,網絡蜘蛛下載了一個網頁,從網頁中提取到新的URL后,需要判斷該URL是否已經存在于列表中。此時,Bloom-Filter算法是最好的選擇。
  比如說,一個象 Yahoo,Hotmail 和 Gmai 那樣的公眾電子郵件(email)提供商,總是需要過濾來自發送垃圾郵件的人(spamer)的垃圾郵件。一個辦法就是記錄下那些發垃圾郵件的 email 地址。由于那些發送者不停地在注冊新的地址,全世界少說也有幾十億個發垃圾郵件的地址,將他們都存起來則需要大量的網絡服務器。
 
  布隆過濾器是由巴頓.布隆于一九七零年提出的。它實際上是一個很長的二進制向量和一系列隨機映射函數。我們通過上面的例子來說明起工作原理。
 
  假定我們存儲一億個電子郵件地址,我們先建立一個十六億二進制(比特),即兩億字節的向量,然后將這十六億個二進制位全部設置為零。對于每一個電子郵件地址 X,我們用八個不同的隨機數產生器(F1,F2, ...,F8) 產生八個信息指紋(f1, f2, ..., f8)。再用一個隨機數產生器 G 把這八個信息指紋映射到 1 到十六億中的八個自然數 g1, g2, ...,g8。現在我們把這八個位置的二進制位全部設置為一。當我們對這一億個 email 地址都進行這樣的處理后。一個針對這些 email 地址的布隆過濾器就建成了。(見下圖) 現在,讓我們看看如何用布隆過濾器來檢測一個可疑的電子郵件地址 Y 是否在黑名單中。我們用相同的八個隨機數產生器(F1, F2, ..., F8)對這個地址產生八個信息指紋 s1,s2,...,s8,然后將這八個指紋對應到布隆過濾器的八個二進制位,分別是 t1,t2,...,t8。如果 Y 在黑名單中,顯然,t1,t2,..,t8 對應的八個二進制一定是一。這樣在遇到任何在黑名單中的電子郵件地址,我們都能準確地發現。
  布隆過濾器決不會漏掉任何一個在黑名單中的可疑地址。但是,它有一條不足之處。也就是它有極小的可能將一個不在黑名單中的電子郵件地址判定為在黑名單中,因為有可能某個好的郵件地址正巧對應八個都被設置成一的二進制位。好在這種可能性很小。我們把它稱為誤識概率。在上面的例子中,誤識概率在萬分之一以下。
  布隆過濾器的好處在于快速,省空間。但是有一定的誤識別率。常見的補救辦法是在建立一個小的白名單,存儲那些可能別誤判的郵件地址。
     
     
*/
 
// 使用php程序來描述上面的算法
 
 
$set = array(1,2,3,4,5,6);
// 判斷5是否在$set 中
 
$bloomFiter = array(0,0,0,0,0,0,0,0,0,0);
 
// 通過某種算法改變$bloomFiter 中位數組表示集合,這里我們使用簡單的算法,把集合中對應的value 對應到bloom中的位置變成1
 
// 算法如下
 
 
foreach($set as $key){
    
    $bloomFiter[$key] = 1 ;
}
 
var_dump($bloomFiter) ;
 
//此時 $bloomFiter = array(1,1,1,1,1,1);
 
//判斷是否在集合中
 
 if($bloomFiter[9] ==1){
     echo '在set 中';
 }else{
     echo '不在set 中' ;
 }
 
 
 // 上面只是一個簡單的例子,實際上哈希算法需要好幾個,但另一方面,如果哈希函數的個數少,那么位數組中的0就多
 
 
 class bloom_filter {
 
 function __construct($hash_func_num=1, $space_group_num=1) {
  $max_length = pow(2, 25);
  $binary = pack('C', 0);
 
  //1字節占用8位
  $this->one_num = 8;
 
  //默認32m*1
  $this->space_group_num = $space_group_num;
  $this->hash_space_assoc = array();
 
  //分配空間
  for($i=0; $i<$this->space_group_num; $i++){
   $this->hash_space_assoc[$i] = str_repeat($binary, $max_length);
  }
 
  $this->pow_array = array(
   0 => 1,
   1 => 2,
   2 => 4,
   3 => 8,
   4 => 16,
   5 => 32,
   6 => 64,
   7 => 128,
  );
  $this->chr_array = array();
  $this->ord_array = array();
  for($i=0; $i<256; $i++){
   $chr = chr($i);
   $this->chr_array[$i] = $chr;
   $this->ord_array[$chr] = $i;
  }
 
  $this->hash_func_pos = array(
   0 => array(0, 7, 1),
   1 => array(7, 7, 1),
   2 => array(14, 7, 1),
   3 => array(21, 7, 1),
   4 => array(28, 7, 1),
   5 => array(33, 7, 1),
   6 => array(17, 7, 1),
  );
 
  $this->write_num = 0;
  $this->ext_num = 0;
 
  if(!$hash_func_num){
   $this->hash_func_num = count($this->hash_func_pos);
  }
  else{
   $this->hash_func_num = $hash_func_num;
  }
 }
 
 function add($key) {
  $hash_bit_set_num = 0;
// 離散key
  $hash_basic = sha1($key);
//  截取前4位,然后十六進制轉換為十進制
  $hash_space = hexdec(substr($hash_basic, 0, 4));
//  取模
  $hash_space = $hash_space % $this->space_group_num;
 
  for($hash_i=0; $hash_i<$this->hash_func_num; $hash_i++){
   $hash = hexdec(substr($hash_basic, $this->hash_func_pos[$hash_i][0], $this->hash_func_pos[$hash_i][1]));
   $bit_pos = $hash >> 3;
   $max = $this->ord_array[$this->hash_space_assoc[$hash_space][$bit_pos]];
   $num = $hash - $bit_pos * $this->one_num;
   $bit_pos_value = ($max >> $num) & 0x01;
   if(!$bit_pos_value){
    $max = $max | $this->pow_array[$num];
    $this->hash_space_assoc[$hash_space][$bit_pos] = $this->chr_array[$max];
    $this->write_num++;
   }
   else{
    $hash_bit_set_num++;
   }
  }
  if($hash_bit_set_num == $this->hash_func_num){
   $this->ext_num++;
   return true;
  }
  return false;
 }
 
 function get_stat() {
  return array(
   'ext_num' => $this->ext_num,
   'write_num' => $this->write_num,
  );
 }
}
 
 
//test
//取6個哈希值,目前是最多7個
$hash_func_num = 6;
 
//分配1個存儲空間,每個空間為32M,理論上是空間越大誤判率越低,注意php.ini中可使用的內存限制
$space_group_num = 1;
 
$bf = new bloom_filter($hash_func_num, $space_group_num);
 
$list = array(
 'http://test/1',
 'http://test/2',
 'http://test/3',
 'http://test/4',
 'http://test/5',
 'http://test/6',
 'http://test/1',
 'http://test/2',
);
foreach($list as $k => $v){
 
 if($bf->add($v)){
  echo $v, "\n";
 }
}
print_r($bf->get_stat());

延伸 · 閱讀

精彩推薦
主站蜘蛛池模板: 超碰97最新 | 看免费黄色大片 | 精品999www | 精品黑人一区二区三区国语馆 | 国产精品一区在线免费观看 | 国产在线播放一区二区 | 日韩黄色片在线观看 | 午夜爽爽爽男女免费观看hd | 99久久视频| 久久精品欧美视频 | 亚洲日本欧美 | 久久精品亚洲欧美日韩精品中文字幕 | 成年片在线观看 | 免费看成年人视频在线 | 欧美一区二区三区四区五区动图 | 久久精品成人 | 欧美日韩大片在线观看 | 特片网久久 | 欧美成人免费一区二区三区 | 国产精品视频一区二区三区四区五区 | av免费在线观看av | 久久99深爱久久99精品 | 亚洲一区在线视频 | 免费一级a毛片在线播放视 日日草夜夜操 | 日韩在线视频一区二区三区 | 27xxoo无遮挡动态视频 | 九九热视频这里只有精品 | 成人在线精品视频 | 91在线色 | 久久久国产一区二区三区 | 久久国产精品二国产精品中国洋人 | 国产外围在线 | 高清视频91 | 精品一区二区三区中文字幕老牛 | 在线a视频 | 91精品久久久久久久久 | 黄色免费高清网站 | 毛片免费视频在线观看 | 欧美成人做爰高潮片免费视频 | 久久精品中文字幕一区二区三区 | 一本大道av |