KMP(内含next数组讲解) —— 剪花布条 ( HDU 2087 )

来源:互联网 发布:linux 如何退出vim 编辑:程序博客网 时间:2024/06/09 19:12
  • 关于KMP算法前缀next最同俗易懂的解释请看:
    http://blog.csdn.net/yearn520/article/details/6729426

  • next数组代码:(将第一位赋值为-1,无重复位置赋值为0,重复位一次递增)

void SetNext()//子串的next数组,如果只看代码的话,很难得出值的确定方法。{    int i=0,j=-1;    Next[0]=-1;    while(i<M)    {        if(j==-1||b[i]==b[j])//b为模式数组        {            i++; j++;            Next[i]=j;        }        else        j=Next[j];    }}
  • KMP匹配代码:(依赖上面的SetNex()函数)
int Kmp(){    int i=0,j=0;    SetNext();    while(i<N)//a为目标数组    {        if(j==-1||a[i]==b[j])//这里j=-1的情况就是第一个字符不匹配的情况。        {            i++;j++;        }        else        j=Next[j];//如果匹配不上,这里回溯j,        if(j==M)//如果匹配成功了。        return i-j+1;//回溯j最终的位子。    }    return -1;}
  • 练习:
    http://acm.hdu.edu.cn/showproblem.php?pid=2087

  • 分析&题解:
    很裸的KMP,计算目标字符串中含有多少个子串。修改一下KMP函数,每匹配完成一次,计数++,直到匹配不了为止。

  • AC代码:

#include <iostream>#include <cstring>#include <cstdio>#include <queue>#include <algorithm>#include <cmath>using namespace std;int N,M;char a[1234];char b[1234];int Next[1234];int cnt ;void SetNext()//子串的next数组,如果只看代码的话,很难得出值的确定方法。{    int i=0,j=-1;    Next[0]=-1;    while(i<M)    {        if(j==  -1||b[i]==b[j])        {            i++; j++;            Next[i]=j;        }        else        j=Next[j];    }}void Kmp(){    int i=0,j=0;    SetNext();    while(i<N)    {        if(j== -1||a[i]==b[j])//这里j=-1的情况就是第一个字符不匹配的情况。        {            i++;j++;        }        else        j=Next[j];//如果匹配不上,这里回溯j,        if(j==M)//如果匹配成功了。        {            j = 0;            cnt++;        }    }    return ;}int main(){    while(scanf("%s", &a) )    {        if(a[0] == '#')            break;        cnt = 0;        scanf("%s", &b);        N = strlen(a);        M = strlen(b);        SetNext();        Kmp();        cout << cnt << endl;    }}
0 0
原创粉丝点击