• 关于 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");

                  }

           }

    }

  • 相关阅读:
    Mysql之正则匹配
    定时任务之elastic-job概述
    清晰讲解LSB、MSB和大小端模式及网络字节序
    极光消息推送多环境配置
    基于TSUNG对MQTT进行压力测试-测试结果
    基于TSUNG对MQTT进行压力测试-基础概念温习
    阻塞式/非阻塞式与同步/异步的区别
    干货!Jenkins下配置findbugs、pmd及checkstyle实现代码自动检测
    jar包
    java环境变量及Eclipse自动编译问题
  • 原文地址:https://www.cnblogs.com/Hilda/p/2659096.html
Copyright © 2020-2023  润新知