|
|
常用链接
随笔分类
随笔档案
最新评论
阅读排行榜
评论排行榜
推荐排行榜
Powered by: 博客园
模板提供:沪江博客
|
|
|
|
|
发新文章 |
|
|
2008年5月20日
#include <stdafx.h>
void _tmain(int argc, _TCHAR* argv[])
{
char *psz="#include <stdafx.h>%cvoid _tmain(int argc, _TCHAR* argv[])%c{%c%cchar *psz=%c%s%c;%c%cprintf( psz , 10 , 10 , 10 , 9, 34, psz , 34,10,9,10);%c}" ;
printf( psz , 10 , 10 , 10 , 9, 34, psz , 34,10,9,10);
}
posted @ 2008-05-20 10:38 路见不平 阅读(344) 评论(0) 编辑
2008年4月11日
搜索引擎的第一步,做一个自己的全文引擎,所谓的全文引擎,就是一个倒排表,所谓的倒排表,就是指从词到文档的索引。对于我们通常的文章来讲,是一个文章包含了很多的词,也就是说,文章是关键字,词是内容。那么当我们需要在很多文章中找到所有存在某一个词的文章的时候,在没有倒排索引的情况下,问题出现了,我们必须使用这个词去匹配所有文章的内容,这个效率显然是不能忍受的。这个时候就是倒排索引闪亮登场的时候了,倒排索引就是词是关键字,内容是所有包含这个关键字的文档和位置信息。所以,从理论上来讲,建所引的过程就是从:
Doc => (Word1,Word2....) 转换成
Word1 => (Doc1,Doc2....)的过程。
转换的时候,需要考虑一个性能的问题,因为对于一个文档中的每一个词,首先要做得事情就是察看这个词是不是在文章中已经出现过。这里实际上有两个相似的操作,第一个操作是把这个文章的词转换成倒排的格式,第二个操作是把第一步产生的倒排索引合并到达的索引上面去。我觉得还是分开两部操作比较好,因为如果一次性的把文章中出现的词合并到大的索引上面去,会出现很多次没有必要的比较,从而降低性能。
为了提高创建索引的性能,我想在这里使用一个平衡二叉树,把所有的词作为这个平衡二叉树的节点,这样的话,插入一个节点比较的次数将是ln(n)次的比较,会比线形的n有很大的改善。明天是周末,把这个代码实现了。
To be continued.
posted @ 2008-04-11 21:12 路见不平 阅读(154) 评论(0) 编辑
我是2004年7月份开始做搜索引擎的,到现在也快四年了,期间虽然做过一些和搜索引擎没有关系的杂事,但是基本上算没有中断过。但是总感觉自己对这个东西的理解还是不够深刻,受一个朋友要自己做操作系统的启发,我萌生了自己做一个简单的搜索引擎的想法。我知道自己的缺点,我的缺点就是想法太多,付诸实施的却很少,大部分都是想一想然后就放弃了。我希望这次能够改变我以往的风格,能够把这个事情坚持下去。和以往不同不同的是,我希望以博客的形式,把我这次开发的过程完整的记录下来。
废话不说,先对要做得事情做一个计划吧。
第一步,首先做搜索引擎的核心,做一个全文的引擎,把倒排表建起来。
第二步,倒排表建立好以后,需要做一个查询系统,能支持与或非三种操作,支持纯与条件下的差错查询。
第三步,相关性的排序。
这次算是Version1吧,这次不涉及的东西是蜘蛛,html内容分析提取,中文分词。 OK, Let's go!
(第一个版本我就一个人搞定了,以后如果继续做的话,希望有识之士能够加入。等作到一定的时候,我会申请一个网站,把所有的源代码都公布出来。希望能做出一个中国人自己的Mini版本的Lucene。)
posted @ 2008-04-11 20:28 路见不平 阅读(999) 评论(2) 编辑
2008年3月19日
最近由于工作的原因,总是需要些一些命令行下的批处理文件,这些扩展名为".bat"的文件,是从Dos时代一路传承下来的,所以我们总是喜欢叫他bat文件。从上大学的时候,一直用bat做一些小的东西,从来没有感受到过它的威力,最近用它做一些工作,发现这个东西还真的比较有意思。总结一下,希望对大家的工作能有所帮助。Bat有传统的模式,和Command Extensions两种模式,扩展用法通常是指后者。
最常用的命令:Call,Echo,For,Goto,If,Pause,REM,shift
Call 命令:调用另外的一个批处理文件。常用的方式就是:"Call sample.bat",新扩展的一个用法是 "Call :label arguments",也就是说,你可以用Call来调用Bat文件内部的一段脚本,用exit来退出当前的call调用。如果配合Goto语句的话,实际上是扩展的Bat文件支持了一个Ugly的函数。
这里需要注意的是,Batch脚本的参数(%0 %1 ...)有了一些新的变化:
%* 表示这个批处理文件的所有的参数(%1 %2 ....)
对于每一个%n还有一些扩展:
%~1 删除%1的两端的双引号
%~f1 扩展成%1的全部文件名
%~d1 获取%1的盘符
%~p1 获取%1的文件路径
%~n1 获取%1的文件名称
%~x1 获取%1的扩展名
%~s1 获取短文件名
%~a1 获取文件的属性
%~t1 获取文件的时间
%~z1 获取文件的大小
%~$PATH:1 从指定的PATH环境变量中查找%1并且扩展成全文件名
而且上面的还可以组合,例如:
%~dp1 把%1扩展成盘符和路径
%~nx1 把%1扩展成文件名和扩展名
%~dp$PATH:1 从制定的PATH中搜索%1,并且扩展成盘符和路径的形式
%~ftza1 扩展成dir类似的输出结果,文件名 时间 大小 属性
echo
用来显示一段文字,没有什么好说的。
goto
用来进行跳转:
goto END
:END
也没有什么好说的。
for 命令:
这个里面最复杂的一个命令。
基本形式:
for %variable in (set) DO command [command-parameters]
需要注意的是,这里的variable一定是单个字符的。set可以是一个或者多个文件,也可以使用通配符:
for %f in (*.txt *.log) DO type %f
表示查找当前目录下所有的.txt,.log,在屏幕上打印它的内容。
这里需要注意的是,Do后面可以加()来执行多行的语句;
for %%f in ( *.txt ) DO (
echo process %%f...
type %%f
)
对于扩展的For语句,有如下的几种形式:
for /D %variable IN (set) DO command [command-parameters]
对目录进行操作
for /R [[driver:]path] %varable IN (set) do command [command-parameters]
对一个路径下的所有的目录作指定的操作
for /L %variable IN (start,step,end) DO command [command-parameters]
产生一个列表,例如(1,1,5) 则产生一个(1 2 3 4 5)的列表
for /F ["options"] %variable IN (file-set|"string"|'command') DO command [command-parameters]
这个命令分三种情况,第一个是一个文件的集合,这种情况下,所有的这些文件都会被打开,命令将处理文件的内容。如果IN的括号里面是有双引号的,则是处理这个字符串。如果括号里面的是单引号的话,则是处理执行命令以后的结果。如果指定了usebackq的话,则单引号表示的是字符串,反向的单引号表示执行的命令,这个时候双引号可以用来把包含空格的路径括起来。
一个一个的解释,首先是options,options有如下的选项:
eol=c 只能指定一个字符,以此开始的为注释行。
skip=n 跳过文件的n行
delims=xxx 指出分隔符的结合。缺省的是空格和TAB
tokens=x,y,m-n,* 指定获取的Token.
usebackq 使用反单引号(~键一起的那个)
例如:
for /F "eol=; token=2,3* delims=, " %i IN ( myfile.txt ) do @echo %i %j %k
解析myfile.txt,忽略分号开始的行,%i是第二个,%j是第三个,%k是剩下的所有。
这里需要注意的是,上面%~进行扩展的那些东西,对于FOR循环中的文件变量也是有效的。
for %Z in (*.txt) do (
echo %~fZ
)
上面的命令就是用来显示全路径名的。
IF命令:
IF命令以供有三种形式:
IF [NOT] ERRORLEVEL number command
IF [NOT] string1 == string2 command
IF [NOT] exists file command
非常简单,没有什么好说的,扩展的命令如下:
IF [/I] string1 compare-op string2 command
IF CMDEXTVERSION number command
IF DEFINED variable command
比较操作符如下:
EQU,NEQ,LESS,LEQ,GTR,GEQ,不多说了,很简单。
/I标志增加的时候,忽略大小写。
CMDEXTVERSION有点像ERRORLEVEL,不同的是他和Commend Extensions的内部数字作比较。
DEFINED用来判断一个环境变量是不是被定义。
可以用%ERRORLEVEL%,%CMDEXTVERSION%,%CMDCMDLINE%作变量用,前面两个很好理解,最后一个就是输入的命令行。
注意IF ERRORLEVEL命令,这个判断的是上一个命令的结果,所以一定按照ERRORLEVEL从大到小的顺序进行判断。
Pause命令:
让程序停下来等按键,没有什么好说的。
REM命令,注释,仅此而已
shift命令:
shift /2
修改参数的位置,从第二个参数开始,把后面的一个参数超前挪动一位。%3=>%2,%4=>%3,%0,%1不变。
Choice命令:
提示用户作出选择的命令;支持如下的参数
/C XNC 给出X,N,C三个选择
/N 隐藏提示信息
/CS 支持大小写
/T 10 10秒超时
/D 缺省选择
/M text 提示信息
字符串操作:
操作方法一,用FOR命令来进行操作。
操作方法二,%variable:~start,length%从变量中截取字符串。%variable:replace=candicate%来替换字符串。
set操作:
设置变量,可选的参数是:
/A 用来进行数学运算,支持与C语言一样的操作符
/P 根据用户的输入来设置环境变量
表达式运算:
调用expr来运算。
还可以set /a进行
其他的注意事项:
在写Bat文件的时候,一定要注意在开始和结束的时候setlocal enabledelayedexpansion/endlocal这样你改变的环境不会影响到外面。
最容易出错的地方:
错误的方法:
for ...... do (
set /a index+=1
use .... %index% ...
)
这里所有的%index%都是初始值,而不是你想要的。
下面的才是正确的:
for ...... do (
set /a index+=1
use ... !index!...
)
posted @ 2008-03-19 16:43 路见不平 阅读(4256) 评论(0) 编辑
2007年5月21日
最近召开了一次轰轰烈烈的社区大会,在这次胜利而又成功的大会上,一个非常新鲜的,颠覆性的名词“口碑营销”进入了广大IT界,经济界人士的眼帘。我是一个做IT的人,但是我是一个纯粹作技术的人,原本对这些上层人士玩的感念没有什么特别的兴趣,再加上对于营销之类的东西一窍不通,我对这些东西通常不予置评的。但是,这次,我想说几句这样的话。 察看了一些关于口碑营销的文章,逐渐的看出一些门道来。原来,所谓的颠覆传统的广告模式的方式,其实就是把原来做在门户上的,做在搜索内容边上的广告,完全的融入到社区的内容中间去。让社区的人口口相传,从而让一个产品在社区里面有一个很好的口碑,达到宣传产品的目的。这样的思路,乍一看,是没有什么问题,但是仔细想想,你会发现其中还是有一些问题存在的,有些问题,可能还是致命的。 现在的社区,为了生存,他们做的事情是自己拉来一些广告,或者是直接在网页里面嵌入一些诸如AdSense之类的东西,以希望通过流量或者是点击来获取一些收益。现在的大部分社区,对于他们的内容的管理相对还是比较严格的。因为这些内容,尤其是一些精彩,中肯,客观的内容,是这些社区在同类网站竞争中生存的根本。这些社区都有一些尽职的编辑或者版主们,对一些广告,或者明显的枪手的文章或者删除文章,或者封ID来保证社区的纯洁。因为,在没有很好的盈利模式被开发出来之前,社区的内容的精彩程度,可信度这些东西,是最容易对用户产生黏着力的。那么我们看看这个崭新的“口碑营销”在做什么?他希望把所谓的口碑(其实就是广告)都融入到社区的内容中间去。如果所有上网的网民都是好人,都是正直无私的好人。所有的这些上网的人,发布的文章都是发自内心的评论,他们对某些商品的评价都是客观公正的。那么,我觉得我们的“口碑营销”模式有资格拿2007年诺贝尔经济学奖!但是现实情况会这么简单吗?当我们走进论坛,里面满满登登的全是枪手们的文章,或者为自己的产品唱赞歌,或者捏造一些事实来攻击竞争对手的产品。或者是一些人,根本没有用过人家的东西,完全是冲着网站的积分或者其他的什么东西去的,从而捏造出一个文章来。如果论坛里面充斥了这样的文章,我想知道,各位,你们还愿意去这样的论坛看看吗?象我,一个普通的网民,我是不愿意去这样的论坛转悠的。 这样的模式,对于那些渴望盈利超过一切的社区来讲,从表面上来看,还是很有一些吸引力的。如果这个模式能够推广下去,在初期,由于这些采用这些模式的网站比较少,枪手还相对的比较少,应该是能够给他们带来一些盈利的。说白了,这也是一种广告模式,有效果,就会有人向里面扔钱。但是如果这个模式到中期的时候,我们就会发现我们原先所熟悉的论坛变味了!原来还有几个人说真话的论坛,现在充斥了各种各样的枪手和骗子的文章。到这个时候,这个网站对用户的黏着度就会急剧降低。到大量用户都流失的时候,这个社区也就没有什么存在的价值了!因为因为没有用户,广告商凭什么向里面扔钱?没有内容,用户又不是傻的,凭什么到你那里去让你忽悠?这不就是传说中的“饮鸩止渴”吗? 或许,也是一个好事情,也算是一个革命吧!让现有的那些社区进行一个重新的洗牌!给后来的创业者们一个全新的竞争环境。 让暴风雨来得更加猛烈一些吧!
posted @ 2007-05-21 10:31 路见不平 阅读(164) 评论(0) 编辑
2007年4月17日
正则表达式是我喜欢的东西,正则表达式在字符串处理方面,除了性能问题外,它有着无可比拟的优势。C#中引入了正则表达式的类库,给我们带来了很大的方便。 要在C#中使用正则表达式,需要引用如下的名字空间:
using System.Text; using System.Text.RegularExpressions;
在C#中使用正则表达式,最重要的类是Regex。Regex对象的构造函数参数中最常见的一个是正则表达式的串,另外一个经常使用的是RegexOptions。正则表达式的字符串和正则表达式的语法这里就不罗嗦了,大家有兴趣的话,可以给我写邮件和我讨论讨论。关于RegexOptions,下面是其中一些主要参数的介绍: RegexOptions.Compiled 让C#把正则表达式编译成一个Assembly,这样可以在执行正则的时候启动的更快。这个参数需要注意的事情是,使用这个选项时,正则表达式一定是静态的字符串,而不能使动态的字符串(可以想象,动态字符串是不会有任何效果的)。 RegexOptions.IgnoreCase 让正则表达式匹配的时候忽略大小写。 RegexOptions.Multiline 多行模式正则匹配。 RegexOptions.None 不指定任何的选项。 RegexOptions.RightToLeft 从右向左开始匹配。 RegexOptions.SingleLine 单行模式正则匹配。
下面讨论正则表达式的使用: Regex token = new Regex(@"((?<protocol>[a-zA-Z]*?)://)?(?<domain>[^/]*)(?<path>.*)", RegexOptions.Compiled); Match matchList = token.Match("http://www.sina.com.cn/index.html");
if (matchList.Success) { Console.WriteLine( "Protocol:{0},Domain:{1},Path:{2}" , matchList.Groups["protocol"] , matchList.Groups["domain"] , matchList.Groups["path"]) ; } 上面的是匹配单行的情况,下面的例子是演示的匹配多个结果的情况:
Regex token = new Regex(@"\s*((?<protocol>\w*?)://)?(?<domain>[^\/\s]+)(?<path>[^\s]*)", RegexOptions.Compiled); MatchCollection matches = token.Matches("http://www.sina.com.cn/index.html http://www.microsoft.com ftp://ftp.cav.com/info.zip");
if (matches.Count != 0) { foreach (Match matchList in matches) { Console.WriteLine("Protocol:{0},Domain:{1},Path:{2}", matchList.Groups["protocol"], matchList.Groups["domain"], matchList.Groups["path"]);
foreach (Capture c in matchList.Captures) { Console.WriteLine("Capture:[" + c + "]"); } } }
下面是一个Replace的用法,主要目的是为了演示MatchEvaluator. public static string ReplaceEva(Match match) { return match.Groups["protocol"].Value + "://" + "www.google.com/" + match.Groups["path"].Value; }
Regex token = new Regex(@"\s*((?<protocol>\w*?)://)?(?<domain>[^\/\s]+)(?<path>[^\s]*)", RegexOptions.Compiled); string strNew = token.Replace("www.sohu.com/index.htm",new MatchEvaluator(ReplaceEva)); Console.WriteLine("New Line:{0}", strNew);
MatchEvaluator是一个函数代理,用来处理替换过程中得到的每一个Match。返回的字符串就是替换后的字符串。
最后演示以下最简单的使用正则进行Splite的操作,例子代码如下:
Regex r = new Regex("(-)"); string[] s = r.Split("one-two-banana");
OK, That's all.希望能够对大家有所帮助。
posted @ 2007-04-17 11:26 路见不平 阅读(328) 评论(0) 编辑
2007年4月16日
摘要: 数独是一个很多人都喜欢的游戏。对于这样的问题,我比较喜欢的解决方案是写一个程序来解决这些问题。不过这些问题显然是那种需要回溯需要优化的问题。游戏规则我就不罗嗦了,言归正传。首先是解决数独问题的算法。程序输入,一个9*9的输入矩阵,有数字的地方就是指定的数字,没有数字的地方输入为0。算法的主要思想如下:1、创建一个堆栈trackStack,用来保存用程序填入的格子的信息。2、查找所有的数字为0的地方... 阅读全文
posted @ 2007-04-16 16:10 路见不平 阅读(7132) 评论(21) 编辑
摘要: 最近的一项工作是关于性能提升方面的。要做的第一个事情是要把很多同类型的DataTable合并到一起,查了很多关于DataTable的相关函数以后,我决定用Merge函数来合并这些DataTable。DataTable[] srcTables = ... ;foreach( DataTable src in srcTables ){dest.Merge( src ) ;}但是测试的结果让我很是失望,... 阅读全文
posted @ 2007-04-16 11:54 路见不平 阅读(5983) 评论(14) 编辑
2007年1月26日
posted @ 2007-01-26 10:11 路见不平 阅读(587) 评论(0) 编辑
|
|