加载中…
个人资料
  • 博客等级:
  • 博客积分:
  • 博客访问:
  • 关注人气:
  • 获赠金笔:0支
  • 赠出金笔:0支
  • 荣誉徽章:
正文 字体大小:

串的模式匹配(BF算法和KMP算法)

(2013-07-07 08:37:38)
标签:

串的匹配模式

分类: 数据结构小总结
在编程的过程中,“串”这个线性结构是用得再多不过了,这个串就是程序员熟悉的字符串了:String.那么在编程的过程中,这个类为我们提供了很多的方法,什么插入啊,查询啊,新建啊,销毁啊,等等等等,这些都是语言开发者写好的,那么语言开发者内部算法到底是怎样的呢,这个如果理解了,对编程也有很大的帮助,因为我们可以灵活运用~~精髓就要去学,去用。。
这篇文章记录一下串里面的模式匹配,模式匹配,顾名思义就是给定一个被匹配的字符串,然后用一个字符串模式(模型)去匹配上面说的字符串,看后者是否在前者里面出现。例如:asbansme和bansm匹配,匹配出来的结果是true的,怎样让计算机去理解这个算法?下面记录其中两个方法:
方法一:BF算法
这个方法就是最容易理解的,但是效率很低的算法,但是最后是能解决问题的,就是循环递归匹配了。具体的做法是:从目标字符串的第一个字符开始,和模式串的第一个字符比较,如果相同就向后继续比较,如果有出现不同的,就重新在目标字符串中上次开始的位置+1开始和模式串的第一个字符串进行比较,知道循环完毕。
这个算法比较简单,理解了意思就能写出程序来"教会"电脑去匹配了。
下面就是程序例子,利用BF匹配,实现Contanst功能;
方法二:KMP算法
这个算法就有点叼了,比BF算法快很多,因为利用一些方法避免了一些无必要的循环,看数学式子看得有点头疼,最后理解以后自己抽象成为一个场景,把方法抽象出来,变成场景,然后这样就能利用右脑的图片式记忆来加深理解印象,这个我一直在使用的方法。
先说一下KMP算法是怎么回事吧,先看一下匹配例子,就大概能知道怎么回事了。。。。
http://s13/bmiddle/7b60d05fte0e2004034ac&690
可以看出来,这个算法的关键就是知道next[j]的值,那么就好办了。那么Next[j]的值是怎么算的呢???
下面说一个场景:一行人排在一起,一个接一个,然后每个人手上可能有一张牌,上面写着他的一个朋友的号码,好了,开始!!某一个人j这个人需要找朋友,所以手上没有牌,然后问左边的那个人他的牌是多少号,获得号数以后,然后大喊一声:"多少多少号,给我出列",然后那个号数的人就出列了,然后喊的人看着出列的人看他和左边的朋友是不是一样。如果一样,那么自己手上的号码牌就写上左边那个同学手上牌的号码+1,如果不一样,那么就过去一巴掌打过去出列的人,然后出列的人不服气,看一看手上的牌,然后叫手上牌的号码那个人出列,说:有人打了我一巴掌,你和打我一巴掌的人的左边的那个人比一下是不是一样,如果一样,出手打人的那个人手上牌的号码就是叫朋友去比的那个人手上牌的号码+1,如果不一样,就打一巴掌,然后循环下去。最后如果还是找不到相同的,第一个打人的手上的牌就是0了。好了,大概就这样一个过程,就能找出所有的Next(j)了。
下面用一下:
模式串:abbaaba

j 0 1 2 3 4 5 6
模式t   a b b a a b a
next[j] -1 0 0 0 1 1 2

好了,很方便就能找出来了。
下面用这个next[j]去匹配下:
目标串:bbababbaaba
模式串: abbaaba

第一轮:bbababbaaba                              第二轮:bbababbaaba
        a           匹配失败,next[0]=-1;                a            匹配失败,next[0]=-1;
第三轮:bbababbaaba          第四轮:bbababbaaba
          abb       匹配失败,next[2]=0;                     abbaaba      匹配成功。 

 下面给个程序例子:
首先的是求next[j]的函数:
返回一个Data类型的数组:
Data类型:

结果:
http://s6/mw690/7b60d05fte0e44c681715&690
    可以看出,是正确的了~~~,,然后就是利用这些Next[j]的值进行匹配了。。!!!下面下程序:

private static bool UseKMPToMaching(string TargerString,string ModeString)
        {
            bool Result = false;
            ArrayList NextCount = GetNextCount(ModeString);
            foreach (Data d in NextCount)
            {
                Console.Write(d.Key + "--");
            }
            Console.WriteLine();
            foreach (Data d in NextCount)
            {
                Console.Write(d.Value + "--");
            }
            int i = 0;
            int j=0;
            for (;i<TargerString.Length;)
            {
                
                for (; j < ModeString.Length;)
                {
                    if (j > ModeString.Length - 1)
                        break;
                    if (i > TargerString.Length-1)
                        break;
                    if (TargerString[i] == ModeString[j] && j == ModeString.Length - 1)
                    {
                        Result = true;
                        return Result;
                    }
                    if (TargerString[i]!=ModeString[j])
                    {
                        j = (NextCount[j] as Data).Value;
                        if (j==-1)
                        {
                            i++;
                            j = 0;
                        }
                    }
                    else
                    {
                        ++i;
                        ++j;
                    }
                }
            }
            return Result;
        }
结果:
OK了!!!试一下别的字符串也无妨~~

0

阅读 收藏 喜欢 打印举报/Report
  

新浪BLOG意见反馈留言板 欢迎批评指正

新浪简介 | About Sina | 广告服务 | 联系我们 | 招聘信息 | 网站律师 | SINA English | 产品答疑

新浪公司 版权所有