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

              }

       }

}

posted on 2012-08-27 20:20  crying_Dream  阅读(179)  评论(0编辑  收藏  举报