zoukankan      html  css  js  c++  java
  • 关于 KMP

      发现KMP, 我都已经忘了,找到我之前写的总结,粘贴一下,保存留念吧;

      发现之前我写的总结和你好玩的样子,自己都看笑了...hia hia hia hia...

    KMP我只了解你一点点

    KMP:即串模式匹配,(KMP分别是三个人名字的简称)。

    学习KMP推荐:严蔚敏数据结构课件。真心说她讲的很到位。能让你明白next[],的求法。

    简单算法基本思想(当字符串长度不大时):用i, j指主串和模式串。通过一个个比较,直至模式串与主串一一匹配则称匹配成功,否则失败。

    改进办法:不用将i指针一次次回朔,而是利用以匹配的结果是是模式串尽可能的向前滑动。

               这里需要一个next[100], 的函数。

    函数模板:KMP() 与 get_next();(详见数据结构严蔚敏版,84页)

    KMP应用:

    http://acm.hdu.edu.cn/showproblem.php?pid=1711

    代码如下:

    #include<stdio.h>

    #include<string.h>

    int m, n, next[10005];

    int xx[1000005], yy[10005];

    void get_next()

    {

           int i, j;

           i=1;

           j=0;      //j=1;  j写成1,害我WA了N次

           next[1]=0;

           while(i<=n)

           {

                  if(j==0||yy[i]==yy[j])

                  {

                         i++;

                         j++;

                         if(yy[i]!=yy[j])

                                next[i]=j;

                         else

                                next[i]=next[j];

                  }

                  else

                         j=next[j];

           }

    }

    int KMP( )

    {

           int i, j;

           i=1;

           j=1;

           while(i<=m && j<=n)

           {

                  if(j==0||xx[i]==yy[j])

                  {

                         i++;

                         j++;

                  }

                  else

                         j=next[j];

           }

           if(j>n)

                  return i-n;

           else

                  return -1;

    }

    int main()

    {

           int p, i, j;

           scanf("%d", &p);

           while(p--)

           {

                  scanf("%d%d", &m, &n);

                  memset(xx, 0, sizeof(xx));

                  memset(yy, 0, sizeof(yy));

                  for(i=1; i<=m; i++)

                         scanf("%d", &xx[i]);

                  for(j=1; j<=n; j++)

                         scanf("%d", &yy[j]);

                  get_next();

                  printf("%d\n", KMP());

           }

    }

    http://acm.hdu.edu.cn/showproblem.php?pid=2087

    代码如下:

    #include<stdio.h>

    #include<string.h>

    char str[1010], str1[1010];

    int next[1010];

    int len, len1;

    void get_next()

    {

           int i, j;

           i=0; j=-1;   //*这里注意导致我WA不要写成 i=1; j=0;

           next[0]=-1;   //*不要把第一个弄没写成next[1]=0;

           while(i<len1)

           {

                  if(j==-1||str1[j]==str1[i])

                  {

                         j++;

                         i++;

                         if(str1[i]!=str1[j])

                                next[i]=j;

                         else

                                next[i]=next[j];

                  }

                  else

                         j=next[j];

           }

    }

    int KMP()

    {

           get_next();

           int i, j;

           i=0;

           j=0;

           int sum=0;

           while(i<len)

           {

                  if(j==len1)

                  {

                         sum++;

                         j = 0;

                  }

                  if(str[i]==str1[j]||j==-1)

                  {

                         i++;

                         j++;

                  }

                  else

                         j = next[j];

           }

           if(j==len1)

                  sum++;

           return sum;

    }

    int main( )

    {

           int i, j;

           while(scanf("%s", str)&&(strcmp(str, "#")!=0))

           {

                  scanf("%s", str1);

                  len = strlen(str);

                  len1 = strlen(str1);

                  int place = KMP();

                  printf("%d\n", place);

           }

    }

    http://acm.hdu.edu.cn/showproblem.php?pid=2203

    说这道题我的话就多了:

    思想:将主串弄成一个环,然后与匹配串进行一一比较,省下了指针回朔的时间:

    超时代码:

    #include<stdio.h>

    #include<string.h>

    int main()

    {

           int i, j, len, len1;

           char str[100005], str1[100005];

           while(scanf("%s%s", str, str1)!=EOF)

           {

                  len = strlen(str);

                  len1 = strlen(str1);

                  if(len<len1)

                         printf("no\n");

                  else

                  {

                         i = 0;

                         j = 0;

                         while(j<len1)

                         {

                                if(str[i]==str1[j])

                                {

                                       str[i]=' ';

                                       i=0;

                                       j++;

                                }

                                else

                                       i++;

                                if(i==len)

                                       break;

                         }

                         if(j==len1)

                                printf("yes\n");

                         else

                                printf("no\n");

                  }

           }

    }

    法一:利用字符数组,strstr()函数:找出str2字符串在str1字符串中第一次出现的位置(不包括str2的串结束符)。 返回值:返回该位置的指针,如找不到,返回空指针。

    代码如下:

    #include<stdio.h>

    #include<string.h>

    int main()

    {

           int i, j, len, len1;

           char str[100005], str1[100005];

           while(scanf("%s%s", str, str1)!=EOF)

           {

                  len = strlen(str);

                  len1 = strlen(str1);

                  if(len<len1)

                         printf("no\n");

                  else

                  {

                         char str3[200005];

                         strcpy(str3, str);

                         strcat(str3, str);

                         if(strstr(str3, str1))

                                printf("yes\n");

                         else

                                printf("no\n");

                  }

           }

    }

    法二:用string 串中的find()函数:find()函数是查找字串在str1中的位置,如果找不到就是string::npos,如果找到了就是在str1中的索引。

    代码如下:

    #include<stdio.h>

    #include<string.h>

    #include<string>

    using namespace std;

    int main()

    {

           int i, j, len, len1;

           char str[100005], str1[100005];

           string ss, st;

           while(scanf("%s%s", str, str1)!=EOF)

           {

                  len = strlen(str);

                  len1 = strlen(str1);

                  if(len<len1)

                         printf("no\n");

                  else

                  {

                         ss = str;

                         ss += str;

                         st = str1;

                         if(ss.find(st)!=string::npos)  // string::npos 是string串的结束,串到头了

                                printf("yes\n");

                         else

                                printf("no\n");

                  }

           }

    }

  • 相关阅读:
    vscode 简介
    TypeScriot 深入
    TypeScript 三斜线指令
    Mysql基础(二十二):表操作:创建,删除,修改,查询表
    Mysql基础(十):函数(四)分组函数
    Mysql基础(九):函数(三)流程控制函数(IF/CASE WHEN)
    Mysql基础(七):函数(一)常见函数/单行函数分类/数学函数/日期函数/其他函数
    Mysql基础(六):sql查询(六)分页查询/联合查询
    Mysql基础(五):sql查询(五)子查询
    Mysql基础(四):sql查询(四)连接查询
  • 原文地址:https://www.cnblogs.com/Hilda/p/2659096.html
Copyright © 2011-2022 走看看