鱼C论坛

 找回密码
 立即注册
查看: 5648|回复: 13

[技术交流] DS\BF、BM、KMP算法

[复制链接]
发表于 2014-5-22 23:33:14 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能^_^

您需要 登录 才可以下载或查看,没有账号?立即注册

x
本帖最后由 ~风介~ 于 2014-5-23 16:37 编辑

先贴代码,晚一点出详解~ ^_^
BF算法比较简单上一张图:
clipboard.png
  1. #include<stdio.h>
  2. #include<string.h>
  3. #define MAXSTRLEN 255
  4. typedef unsigned char SString[MAXSTRLEN];
  5. int BF_Match(SString s,SString t)
  6. {
  7. int i=0,j=0;
  8. int n=strlen(s),m=strlen(t);

  9. while((i<n)&&(j<m))
  10. {
  11.   if(s[i]==t[j]) /*匹配成功后,继续下一轮匹配,最后匹配成功后,i和j还要加一,然后跳出循环*/
  12.   {
  13.    i++;
  14.    j++;
  15.   }
  16.   else /*匹配失败,i回溯j置零,下一趟匹配*/
  17.   {
  18.    i = i-j+1;
  19.    j=0;
  20.   }
  21. }
  22. if(j==m)/*如果匹配成功的话,返回匹配成功的第一个位置*/
  23.   return (i-m);
  24. else
  25.   return -1;
  26. }
  27. int main()
  28. {
  29. SString s,t;
  30. int i;
  31. printf("请输入主串s:");
  32. scanf("%s",s);
  33. printf("请输入模式串t:");
  34. scanf("%s",t);

  35. i = BF_Match(s,t);
  36. if(i!= -1)
  37. {
  38.   printf("模式串在主串中第一次出现的下标为:%d\n",i);
  39. }
  40. else
  41. {
  42.   printf("主串中不存在模式串!\n");
  43. }

  44. return 0;

  45. }
复制代码
BM算法
  1. #include<stdio.h>
  2. #include<string.h>
  3. #define MAXSTRLEN 255
  4. typedef unsigned char SString[MAXSTRLEN];
  5. int BM(SString S,SString T)
  6. {
  7. int lenS,lenT,i,j;
  8. lenS=strlen(S);
  9. lenT=strlen(T);
  10. for(i=0;i<=lenS-lenT;i++)/*当主串的字符小于模式串t时停止*/
  11. {
  12.   if(T[0]==S[i]&&T[lenT-1]==S[i+lenT-1])/*比较第一个和最后一个字符*/
  13.   {
  14.    for(j=1;j<lenT-1;j++)/*比较*/
  15.    {
  16.     if(T[j]!=S[j+1])
  17.       break;
  18.       }
  19.    if(j==lenT-1) return i+1;
  20.   }
  21. }
  22. return 0;
  23. }
  24. int main()
  25. {
  26. int i;
  27. SString S,T;
  28. printf("请输入主串S:");
  29. scanf("%s",S);
  30. printf("请输入模式串T:");
  31. scanf("%s",T);

  32. i=BM(S,T);
  33. if(i==0)
  34.   printf("主串中不存在模式串!\n");
  35. else
  36.   printf("模式串在主串中第一次出现的下标为%d\n",i);

  37. return 0;
  38. }
复制代码
KMP算法
  1. #include<stdio.h>
  2. #include<string.h>
  3. #define MAXSTRLEN 255
  4. typedef unsigned char SString[MAXSTRLEN];
  5. void get_next(SString T, int next[])
  6. {
  7. int lenT,i=1,j=0;
  8. lenT=strlen(T);
  9. next[1]=0;
  10. while(i<lenT)
  11. {
  12.   if(j==0 || T[i-1]==T[j-1])
  13.   {++i; ++j; next[i]=j;}
  14.   else
  15.    j=next[j];
  16. }
  17. printf("模式串T的next函数值为:");
  18. for(i=1;i<=lenT;i++)
  19.   printf("%d ",next[i]);
  20. printf("\n");
  21. }
  22. int KMP(SString S, SString T)
  23. {
  24. int next[MAXSTRLEN];
  25. int lenS,lenT,i=1,j=1;
  26. lenS=strlen(S);
  27. lenT=strlen(T);
  28. get_next(T,next);
  29. while(i<=lenS && j<=lenT)
  30. {
  31.   if(j==0 || S[i-1]==T[j-1])
  32.   {++i; ++j;}
  33.   else
  34.    j=next[j];
  35. }
  36. if(j>lenT) return i-lenT;
  37. else return 0;
  38. }
  39. int main()
  40. {
  41. SString S,T;
  42. int i;
  43. printf("请输入主串S:");
  44. scanf("%s",S);
  45. printf("请输入模式串T:");
  46. scanf("%s",T);
  47. i=KMP(S,T);
  48. if(i==0)
  49.   printf("主串中不存在模式串!\n");
  50. else
  51.   printf("模式串在主串中第一次出现的下标为%d\n",i);


  52. return 0;
  53. }
复制代码



本帖被以下淘专辑推荐:

小甲鱼最新课程 -> https://ilovefishc.com
回复

使用道具 举报

发表于 2014-5-23 12:25:36 | 显示全部楼层
强烈支持楼主中。。。。
运行了BF算法程序,添加了一些注释和一小点修改:
  1. #include<stdio.h>
  2. #include<string.h>

  3. #define MAXSTRLEN 255

  4. //typedef unsigned char SString[MAXSTRLEN];  //mingw中报错:不能把‘unsigned char*’
  5.                                                                                          //转换为'const char*'  所以修改如下:
  6. typedef char SString[MAXSTRLEN]        ;                                                         

  7. /*************************************
  8. /*      BF                            *
  9. **************************************/
  10. int BF_Match(SString MainStr,SString PattStr)
  11. {
  12.         int i=0,j=0;
  13.         int iMainStrLen=strlen(MainStr),iPattStrLen=strlen(PattStr);  //取得字符串长度

  14.          while((i<iMainStrLen)&&(j<iPattStrLen))
  15.         {
  16.                   if(MainStr[i]==PattStr[j]) /*最后匹配成功后,i和j还要加一,然后跳出循环*/
  17.                   {
  18.                            i++;
  19.                            j++;
  20.                   }
  21.                   else /*匹配失败,i回溯,下一趟匹配*/
  22.                   {
  23.                            i = i-j+1;
  24.                            j=0;
  25.                   }
  26.          }
  27.          if(j==iPattStrLen)                /*匹配成功*/
  28.                   return (i-iPattStrLen);
  29.          else
  30.                   return -1;
  31. }

  32. //----------------main func------------------
  33. int main()
  34. {
  35.          SString MainStr,PattStr;
  36.          int i;
  37.          printf("请输入主串MainStr:");
  38.          //scanf("%s",MainStr);  //不能读空格
  39.          gets(MainStr);
  40.          printf("请输入模式串PattStr:");
  41.          //scanf("%s",PattStr);
  42.          gets(PattStr);

  43.          i = BF_Match(MainStr,PattStr);        //调用BF匹配算法
  44.          if(i!= -1)                        //匹配成功
  45.          {
  46.                   printf("模式串在主串中第一次出现的下标为:%d\n",i);
  47.          }
  48.          else
  49.          {
  50.                   printf("主串中不存在模式串!\n");
  51.          }

  52.          return 0;
  53. }
复制代码

评分

参与人数 2荣誉 +10 鱼币 +15 贡献 +3 收起 理由
拈花小仙 + 5 + 5 顶一下,加油哦~
~风介~ + 5 + 10 + 3 感谢楼主无私奉献!

查看全部评分

小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 1 反对 0

使用道具 举报

发表于 2014-5-23 12:58:39 | 显示全部楼层
强烈支持楼主。。。。
BM算法个人见解。。。。。修改了一下地方
  1. #include<stdio.h>
  2. #include<string.h>

  3. #define MAXSTRLEN 255

  4. ///typedef unsigned char SString[MAXSTRLEN];  ///
  5. typedef char SString[MAXSTRLEN];



  6. int BM(SString MainStr,SString PattStr)
  7. {
  8.         int iMainStrLen,iPattStrLen,i,j;
  9.         iMainStrLen=strlen(MainStr);                //获取字符串长度
  10.         iPattStrLen=strlen(PattStr);
  11.          
  12.         for(i=0;i<=iMainStrLen-iPattStrLen;i++)/*当主串的字符小于模式串t时停止*/
  13.         {
  14.                   if(PattStr[0]==MainStr[i]&&PattStr[iPattStrLen-1]==MainStr[i+iPattStrLen-1])/*比较第一个和最后一个字符*/
  15.                   {
  16.                          
  17.                           //下面无法处理模式字符串PattStr的长度为1,如果iPattStrLen=1了
  18.                         // 则不进入for循环,但是现在j=1
  19.                         //下面的if判断语句则不能return(此时已经匹配成功的,但不能返回)
  20.                         //于是在for循环后面加一句 if(iPattStrLen==1) return i;
  21.                            for(j=1;j<iPattStrLen-1;j++)/*比较*/
  22.                            {
  23.                             //if(T[j]!=S[j+1])  /////////这里应该是j+i
  24.                             if(PattStr[j]!=MainStr[j+i])
  25.                                       break;
  26.                       }
  27.                             if(iPattStrLen==1) return i;
  28.                            if(j==iPattStrLen-1) return i; //匹配成功 指示在主字符串中的下标,这里应该返回i而不是i+1吧
  29.                   }
  30.         }
  31.         return 0;
  32. }
  33. //-------------main func--------
  34. int main()
  35. {
  36.         int i;
  37.         SString MainStr,PattStr;
  38.         printf("请输入主串MainStr:");
  39.         //scanf("%s",S);
  40.         gets(MainStr);                        //可以读取空格
  41.         printf("请输入模式串PattStr:");
  42.         //scanf("%s",T);
  43.         gets(PattStr);

  44.         i=BM(MainStr,PattStr);
  45.         if(i==0)
  46.                   printf("主串中不存在模式串!\n");
  47.         else
  48.                   printf("模式串在主串中第一次出现的下标为%d\n",i);

  49.         return 0;
  50. }
复制代码

评分

参与人数 2荣誉 +7 鱼币 +15 贡献 +2 收起 理由
拈花小仙 + 5 + 5 热爱鱼C^_^
~风介~ + 2 + 10 + 2 感谢楼主无私奉献!

查看全部评分

小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2014-5-23 14:48:03 | 显示全部楼层
强烈支持楼主中。。。。
KMP这个。。。修改了一些地方,只是个人理解
  1. #include<stdio.h>
  2. #include<string.h>
  3. #define MAXSTRLEN 255
  4. //typedef unsigned char SString[MAXSTRLEN];
  5. typedef char SString[MAXSTRLEN];


  6. //---------GetNext-------------------------
  7. /* KMP最核心的便是如何确定next数组,即模板字符串PattStr与
  8. /* 主字符串MainStr不匹配时 ,下次该从何处开始匹配
  9. /*比如模板字符串  PattStr=abchabcdaab
  10. /*与主字符串匹配时当 PattStr[6]='c'与主字符串MainStr不匹配,
  11. /*例如主字符串MainStr= ... abchabf...(省略号代码还有其他字符,只没有写出来)
  12. /*发现主字符串中不匹配的'f'前的'ab'和开头ab一样,所以此时只需要匹配一下PattStr[2]与'f'是否匹配
  13. /*而不用再从PattStr[0]匹配。如何知道主字符串如何与PattStr字符串的第3个字符比较呢?这就引进了next
  14. /*数组,来存储这个PattStr的下标值。    ---额,上面说得不好 :-(
  15. /*
  16. /*******************************************
  17. /*求next数组,举一个例子(用上面的例子):
  18. /* PattStr = abchabcdaab
  19. /*则 next = -1,0,0,0,-1,0,0,3,-1,1,0
  20. /* 这里要理解 PattStr[5]andPattStr[6]的next[5]!=1和next[6]!=2 以及 next[9]=1
  21. /*比如主字符串  MainStr= ...abchabd...  当 PattStr[6]='c' 与主字符串相对应的'd'不匹配时
  22. /*next[6]=2还是等于0呢?如果等于2,则用 PattStr[2]='c'继续与主字符串比较,但这明显重复运算了,所以此时next[6]=0
  23. */
  24. void GetNext(SString PattStr, int next[])
  25. {
  26.         int iPattStrLen,i=0,j=-1;
  27.         iPattStrLen=strlen(PattStr);  //获得模式字符串的长度
  28.         next[0]=-1;                                        //next[0]初始化为-1,任何串的第一个字符的模式值规定为-1。
  29.        
  30.         while(i < iPattStrLen-1)
  31.         {
  32.                   if(j==-1 || PattStr[i]==PattStr[j])
  33.                 {
  34.                         ++i;
  35.                         ++j;
  36.                         //下面4行修改了 即是实现了上面的next[6]=0而不等于2的功能
  37.                         if(PattStr[i] != PattStr[j])                 
  38.                                 next[i]=j;
  39.                         else
  40.                                 next[i]=next[j];
  41.                 }
  42.                   else
  43.                            j=next[j];
  44.         }
  45.        
  46.         printf("模式串PattStr的next函数值为:");
  47.         for(i=0;i<=iPattStrLen-1;i++)
  48.                   printf("%d ",next[i]);
  49.         printf("\n");
  50. }

  51. //-------------KMP----------
  52. int KMP(SString MainStr, SString PattStr)
  53. {
  54.         int next[MAXSTRLEN];
  55.         int iMainStrLen,iPattStrLen,i=0,j=0;
  56.         iMainStrLen=strlen(MainStr);        //获得字符串长度
  57.         iPattStrLen=strlen(PattStr);
  58.        
  59.         GetNext(PattStr,next);        // 获得next数组
  60.        
  61.         while(i < iMainStrLen && j < iPattStrLen)
  62.         {
  63.                   if(j==-1 || MainStr[i]==PattStr[j])
  64.                 {
  65.                         ++i;
  66.                         ++j;
  67.                 }
  68.                   else
  69.                            j=next[j];
  70.         }
  71.         if(j>=iPattStrLen) return i-iPattStrLen;  //匹配成功
  72.         else return 0;
  73. }

  74. //------------main func--------------
  75. int main()
  76. {
  77.         SString MainStr,PattStr;
  78.         int i;
  79.         printf("请输入主串MainStr:");
  80.         //scanf("%s",S);
  81.         gets(MainStr);        //可以获得空格字符
  82.         printf("请输入模式串PattStr:");
  83.         //scanf("%s",T);
  84.         gets(PattStr);
  85.           
  86.         i=KMP(MainStr,PattStr);  //调用KMP
  87.        
  88.         if(i==0)
  89.                   printf("主串中不存在模式串!\n");
  90.         else
  91.                   printf("模式串在主串中第一次出现的下标为%d\n",i);

  92.         return 0;
  93. }
复制代码

评分

参与人数 1荣誉 +3 鱼币 +10 贡献 +2 收起 理由
~风介~ + 3 + 10 + 2 感谢楼主无私奉献!

查看全部评分

小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2014-6-12 22:15:47 | 显示全部楼层

学习一下~~
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2015-1-22 16:07:52 | 显示全部楼层
elvo 发表于 2014-5-23 12:58
强烈支持楼主。。。。
BM算法个人见解。。。。。修改了一下地方

对于单个字符就检测不到!\n
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2015-1-23 01:39:15 | 显示全部楼层
看毛片算法还是有点难呀,学习下。
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2015-1-23 01:39:54 | 显示全部楼层
支持下小甲鱼。
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2015-1-24 09:31:52 | 显示全部楼层
学习一下
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2015-5-23 13:38:12 | 显示全部楼层
支持支持
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2015-8-24 22:34:43 | 显示全部楼层
留着看看
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2015-9-23 20:10:39 | 显示全部楼层
我是来领鱼币的
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2015-10-7 16:13:43 | 显示全部楼层
cool
小甲鱼最新课程 -> https://ilovefishc.com
回复

使用道具 举报

发表于 2015-10-25 14:14:55 | 显示全部楼层
对照算法实际应用,理解更快。
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号-1 | 粤公网安备 44051102000585号)

GMT+8, 2025-5-22 15:23

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表