我写的这个简单模式匹配方法目前还是一个半成品,还有一些地方需要完善,没有考虑在匹配多个字符串的时候各个字符串的hashcode值之和可能会大于Int64.MaxValue,当然绝大部分情况下不会发生溢出问题。
主要思想:
暂且先把要被查找的字符串称为源字符串, 要匹配的字符串叫目标字符串好了。
1: 对目标字符串所有字符进行一个Hashcode求和运算。
2:同时对在源字符串对同样长度(该长度必须与目标字符串的长度相同,这样可以保证一个求和的hascode表示一个唯一的字符串)的字符进行一个hashcode求各运算。
3:比较二个hashcode值,如果相等则表示匹配成功,否则继续滑动目标字符串,源字符串前进一位,同时计算源字符串的hashcode值,依此类推,直接匹配到字符串为止
代码:
1 public static bool Match(this string src,string pattern)
2 {
3 int patternLen = pattern.Length;
4 int srcLen = src.Length;
5
6 if (srcLen == 0 || srcLen < patternLen)
7 {
8 return false;
9 }
10
11 long patternHashCode = 0;
12 long srcHashCode = 0;
13
14
15 for (int i = 0; i < patternLen; i++)
16 {
17 patternHashCode += pattern[i].GetHashCode();
18 srcHashCode += src[i].GetHashCode();
19 }
20
21 int j = 0;
22
23 do
24 {
25 if (patternHashCode == srcHashCode)
26 {
27 return true;
28 }
29 if (j + patternLen < srcLen)
30 {
31 srcHashCode = srcHashCode - src[j].GetHashCode() + src[j + patternLen].GetHashCode();
32 }
33 }
34 while (j++ < srcLen);
35
36 return false;
37 }
下面我比较了一下该算法与IndexOf的性能,我读取一个将近12M的文本文件,分别用Match与IndexOf来匹配指定的字符串,测试代码如下:
test code
1 static void Main(string[] args)
2 {
3
4 string text = "";
5 string pattern = "淡泊以明志,宁静以致远";
6
7 FileStream fs = new FileStream("刘太医谈养生.TXT", FileMode.Open);
8 using (StreamReader sr = new StreamReader(fs,Encoding.GetEncoding("gb2312")))
9 {
10 text = sr.ReadToEnd();
11 }
12
13
14 Stopwatch sw = Stopwatch.StartNew();
15 sw.Start();
16 bool result = text.Match(pattern);
17 sw.Stop();
18
19 Console.WriteLine("pattern search\r\nfound:{0},elpased:{1}ms", result, sw.ElapsedMilliseconds);
20
21 sw.Restart();
22 result = text.IndexOf(pattern) >= 0;
23 sw.Stop();
24
25
26 Console.WriteLine("index of search\r\nfound:{0},elpased:{1}ms", result, sw.ElapsedMilliseconds);
27
28 Console.Read();
29 }
测试结果,我直接截了一张图:
差距就不说了,IndexOf时间都耗在对字符串的索引访问的地方,当一个字符串非常长的时候,访问指定位置的索引就需要移动指针,字符串越长,移动指针的次数据就越多,而且还是在一个循环当中,这样性能差距就体现出来了。