2010年6月21日
最近准备学习一下搜索引擎方面的技术。找到一本很好的入门书籍,梁斌写的《走进搜索引擎》。粗略地看一下,这本书对于像我这样的新手详略得当,介绍的很全面,是一本很好的入门书籍。
在引言中,作者提到了公认的搜索引擎的三种服务方式:
1.目录是搜索引擎
这类引擎提供了一份人工按类别编排的网站目录,各类下边排列着属于这一类别的网站的站名和网址链接,再记录一些摘要信息,对该网站进行概述性介绍。因为人工编排,搜索信息准确,导航质量高;不足时数据量有限,更新不及时,人工维护成本高。总之,这类搜索引擎好比一本书的目录,或者索引。
2.全文搜索引擎
它们都是通过从互联网上提取的各个网站的信息(以网页文字为主)而建立的数据库中,检索与用户查询条件匹配的相关记录,然后按一定的排列顺序将结果返回给用户。这类搜索引擎通过以网络爬虫等形式的下载系统,自动从网络中爬去资源,加入索引库。优点是信息量大、更新及时,无需人工干预;缺点是返回信息过多,有很多无关信息。
3.元搜索引擎
元搜索引擎在接受用户查询请求时,同时在其他多个引擎上进行搜索,并将结果返回给用户。著名的元搜索引擎有InfoSpace、Dogpile、Vivisimo等(元搜索引擎列表),中文元搜索引擎中具代表性的有搜星搜索引擎。在搜索结果排列方面,有的直接按来源引擎排列搜索结果,如Dogpile,有的则按自定的规则将结果重新排列组合,如Vivisimo。
接下来搜索引擎的发展历史以及一些知名搜索引擎就略过吧。
第二章 搜索引擎概貌
搜索引擎的主要需求可以分为4种
查得快、查得全、查得准、查得稳
查得快是搜索引擎的一项基本需求,调查表明,公开的搜索引擎查询速度在秒这个量级,而商用搜索引擎的查询速度达到毫秒级,并能支持大规模用户同时访问。影响速度原因有很多,例如索引库的效率、分布查询的处理能力和查询缓存的命中率。
查得全是指检索出的网页占所有相关网页比率高。对于当今海量信息的web查询,这个并不是重要的要求,因为用户需要的不是全部的相关信息,而是其中最重要最关心的几个检索结果。但对于如网站查询,和一些小规模搜索,查全率仍然是重要的指标。
查得准用查准率来衡量,即检索出的相关文档占检索出的总文档的比率。查得准是能否把握用户需求的核心所在,也是搜索引擎能力几乎最重要的方面。是否查得准主要取决于网页排序,如Google著名的pageRank排序。
查得稳指搜索引擎能够7*24长期稳定提供服务。
搜索引擎公认地被分为下载、分析、索引、查询四大系统。这四大系统相互配合,共同满足搜索引擎快、全、准、稳的四大需求。
下载系统负责从万维网上下载各种类型的网页,并且保持对万维网变化的同步。
分析系统抽取下载系统得到的网页数据,进行pageRank和分词计算。
索引系统将分析系统处理后的网页对象索引入库。
查询系统负责分析用户提交的查询请求,从索引库中检索出相关网页并将网页排序后,以查询结果的形式返回给用户。
前三个系统组成了搜索引擎的数据制作部分,被称为“离线部分”;查询系统为搜索引擎的数据服务部分,要求快速响应,被称为在线部分。
2010年3月21日
最近一直在考虑如何选择自己上研究生后的方向,因为对计算机科学类的研究方向也不是很了解,最近一直在阅读关于不同的研究方向和它们的应用的书籍。最后终于确定了自己的研究方向,总结一下自己的思考吧。
我认为自己不属于那种埋头研究型和论文型的人才,我更希望能把知识应用到软件的开发中,做出一些实用的激动人心的软件来,所以理论研究的路线我就不考虑了。从实际的应用出发,我认为软件粗略地可以分为三类----专用型软件,企业级软件,个人应用软件。当然这三类之间界限不是非常的清晰。
首先,专用型软件,类似Photoshop,一些图形图像工作站中应用的软件,MATLAB之类的。人们对于这类软件的需求是比较固定的,变化相对较少。这类软件的市场相对成熟,一些巨型公司不断应用更新的技术去满足用户的这些需求。
其次,企业级软件。这种针对大型企业,多用户,对软硬件需求都较高。这种软件又可以分为两类,一种是通用性企业软件,是基本每个企业都需要的,如财务,人事管理,企业运作,ERP之类。这类软件发展已经很完善,SAP、用友、金蝶等大公司已经占据了市场,从某个层面上讲,这些企业不是在卖软件,而是在卖他们的企业管理思想。另一类就是专门针对企业的业务流程的定制化软件,这类软件发展得前景很大,越来越多的企业将对其业务流程进行电子化。但这种软件的需求需要较强的背景知识,目前国内的软件团队往往往往缺乏这些领域知识,所以开发前需要大量人力物力投入到了解业务需求以及和客户沟通,而最终结果往往不能很好满足客户需要,这种高成本高风险的开发方式最终会被取代。随着需求的发展,应该会有更多针对单个领域进行软件开发的团队,他们都是这一领域的专家,代码可以极大程度上复用,和客户沟通更容易。同时,针对市场预测,数据存储和计算的需求也会相应增强,针对专业领域的技术如计算机视觉,以及高性能计算将会有很大的用武之地。
最后,个人应用软件。一类是走向专业化的个人应用,比如游戏机,独立的硬件平台,专门为这一应用进行过优化。另一种软件则在向云端进发,谷歌的设想会慢慢地变为现实。个人pc的地位逐渐被更小巧,便携,拥有网络接入的手机,PDA以及上网本所取代。这些网络接入设备将越来越流行,无线网络覆盖和网络带宽将不断提高。但目前平台非常多样,软件之间的移植比较困难,往往是针对一个平台进行开发,由app store集中管理,而开发者很多是个人或小型的团体,未来应该会出现更多的专业平台应用开发商。因特网上的数据越来越多。有人形容因特网实际是一个巨大的数据库,只不过里面的数据以非形式化的方式以自然语言存储。那不必说,数据库技术必然会大有前途。对这些海量数据的管理、运算、抽取知识也将是一个发展的热点,就像谷歌做的那样,这需要数据挖掘、搜索、机器学习、人工智能方面的技术,来处理这些数据。相应高性能计算也会有强劲需求。软件的因特网化对信息安全也会有巨大需求。
最近在看一本叫做《集体智慧编程》的书,里面介绍了在web2.0时代,利用海量的世界各地用户制造的数据进行处理的技术,如推荐系统,搜索,文件过滤等等。世界各地大量的人产生了海量的看似杂乱无章的数据,如何从这些数据中提取出有用的信息是一项非常有挑战性的难题。谷歌利用复杂的算法,从因特网中找到用户需求的网页,成就了如今的辉煌。
分析完这些技术的前景,再分析我自己吧。我一直对软件工程有一定的兴趣,但没有强烈到让我下定决心一直把这一领域作为我的方向,我感觉软件工程的知识是每个开发团队都必需的,不管哪一领域,软件工程对于开发都是必需品。老师给我的建议是,选自己的方向首先要不讨厌它,在你比较有兴趣的领域中再去选择一个更有前景的。综上,我决定开始了解数据挖掘、和机器学习以及人工智能关于集体智慧方面的知识,争取在研究生之前先对这些有初步的了解。
个人了解非常有限,片面的分析了一下软件的方向,希望大家能多多批评指正:)
2010年3月11日
题目如下:http://acm.tju.edu.cn/toj/showp1057.html
一开始苦思仍然没找到非枚举的方法,于是用枚举算了一遍,果不其然地超时了。
后来上网搜索后,看到一句提示,可以采用动态规划的方法。
由于题目要求中硬币数量和重量都为整数,可以做一个长度为硬币总重量+1的数组value[i],然后将其全部赋上最大值MAX,value[i]代表硬币总重量为i的情况下,最小可能的价值。然后用value[i]+v[j]去刷新value[i+w[j]]的值即可。相较于枚举来说,这样的方法消除了不同硬币组合产生相同重量的情形,节省了计算时间。
一开始写了一个递归函数去实现这个动态规划

代码
1 void recur(int i, int moneyW, int coinAmount, int valueArray[], int coinV[], int coinW[])
2 {
3 for ( int j=0 ; j<coinAmount ; j++)
4 {
5 if( i+coinW[j] <= moneyW )
6 {
7 if( valueArray[i+coinW[j]] > valueArray[i] + coinV[j] )
8 {
9 valueArray[i+coinW[j]] = valueArray[i] + coinV[j];
10 recur(i+coinW[j], moneyW, coinAmount, valueArray, coinV, coinW);
11 }
12 }
13 }
14 }
将总的问题分为若干小的相同子问题,递归的方式比较直白,给定当前weight,然后用各种硬币去加,不幸又超时了。
这次换着用非递归的方法去求解,逐个处理valueArray[]中的每一个值,若valueArray[i]!=MAX,说明它已被刷新过值,计算valueArray[i+w[j]]对于每种硬币去刷新一遍valueArray

代码
1 #include <iostream>
2 #define MAX 600001
3 using namespace std;
4
5 int main()
6 {
7 int cas;
8 cin>>cas;
9 while( cas > 0 )
10 {
11 int pigW=0;
12 int wholeW=0;
13 int moneyW=0;
14 cin>>pigW;
15 cin>>wholeW;
16 moneyW = wholeW - pigW;
17 int valueArray[moneyW+1];
18 for ( int i=0 ; i< moneyW+1 ; i++ )
19 valueArray[i] = MAX;
20 int coinAmount = 0;
21 cin>>coinAmount;
22 int coinW[coinAmount];
23 int coinV[coinAmount];
24 for ( int i=0; i<coinAmount; i++ )
25 {
26 cin>>coinV[i];
27 cin>>coinW[i];
28 }
29 valueArray[0]=0;
30 //recur(0, moneyW, coinAmount, valueArray, coinV, coinW);
31 for( int i=0; i<=moneyW ; i++)
32 {
33 if(valueArray[i] != MAX)
34 {
35 for(int j=0; j<coinAmount ; j++)
36 {
37 if(i+coinW[j]<=moneyW && valueArray[i+coinW[j]]>valueArray[i]+coinV[j])
38 {
39 valueArray[i+coinW[j]]=valueArray[i]+coinV[j];
40 }
41 }
42 }
43 }
44 //for( int m=0; m<=moneyW ; m++)
45 // cout<<valueArray[m]<<" ";
46 if ( valueArray[moneyW] == MAX )
47 cout<<"This is impossible."<<endl;
48 else
49 cout<<"The minimum amount of money in the piggy-bank is "<<valueArray[moneyW]<<"."<<endl;
50 cas--;
51 }
52 //system("pause");
53 return 0;
54 }