poj3461 (裸kmp)kmp模板

来源:互联网 发布:网络创意 卖给 编辑:程序博客网 时间:2024/05/17 23:55
/*这里是参考的算法导论589页,以及大牛kuangbin的kmp,他的kmp和算法导论代码一致的,博主也看过好多大牛的博客,才选择kuangbin的,因为其他大牛有把模式串代码写的不清楚或直接写错的,kuangbin是完全正确的。*/ #include <iostream>#include <cstdio>#include <algorithm>#include <cstring>#include <map>#include <vector>using namespace std;const int N = 100000+10;char s[N*10], p[N];/* 母串,模式串*/ int nextval[N];/* next数组只和模式串有关因此长度和模式串相同*/ int lens, lenp;/* 母串len、模式串len*/ void getnext()/* 这里是得到next数组的过程此过程只与模式串长度有关*/ {int j = 0;int k = -1;nextval[0] = -1;/*next数组默认值next[0] = -1, next[1] = 0,恒定不变,这个可以根据next数组描述画图看看弄清楚*/ while(j < lenp){/* 这里next数组下标是从0开始的最多next下标到lenp-1,要懂得next数组只和模式串有关和母串无关只求一次即可*/if(k == -1 || p[k] == p[j])/* 这里就是寻找最长真前缀、后缀,的处理过程不懂就根据代码模拟画图很容易懂代码第一次见确实不知道怎么写*/nextval[++j] = ++k;elsek = nextval[k];}}int kmp(){int count = 0;    int i, j=0;/*  i,j分别是母串和模式串下标 */    if(lenp == 1 && lens == 1)    {        if(s[0] == p[0]) return 1;        else return 0;    }    getnext();/* 这里将模式串最长真前缀、真后缀求出*/     for(i = 0; i < lens; i++)/* 母串查找完*/    {        while(j > 0 && s[i] != p[j])          j = nextval[j];/* 这里是模式串回溯过程即模式串向后移动*/        if(p[j] == s[i]) j++;        if(j == lenp)/* 已经找到了一个串*/        {            count++;            j = nextval[j];/* 这里回溯是在母串还没有完全查找完的情况下继续向下查找,所以回溯的,此时因为next数组的个数与模式串长度相同那么此时next[lenp]由于超出模式出长度,即next[lenp] = next[0] = -1,相当于整个串后移一个单位*/        }    }    return count;}int main(){int ncase;int ans;scanf("%d", &ncase);while(ncase--){scanf("%s%s", p, s);lenp = strlen(p);lens = strlen(s);printf("%d\n", kmp());} return 0;}/*和上面一样只是去掉注释而已*/
#include <iostream>#include <cstdio>#include <algorithm>#include <cstring>#include <map>#include <vector>using namespace std;const int N = 100000+10;char s[N*10], p[N];int nextval[N];int lens, lenp; void getnext(){int j = 0;int k = -1;nextval[0] = -1;while(j < lenp){if(k == -1 || p[k] == p[j])nextval[++j] = ++k;elsek = nextval[k];}}int kmp(){int count = 0;    int i, j=0;    if(lenp == 1 && lens == 1)    {        if(s[0] == p[0]) return 1;        else return 0;    }    getnext();    for(i = 0; i < lens; i++)    {        while(j > 0 && s[i] != p[j])          j = nextval[j];        if(p[j] == s[i]) j++;        if(j == lenp)        {            count++;            j = nextval[j];        }    }    return count;}int main(){int ncase;int ans;scanf("%d", &ncase);while(ncase--){scanf("%s%s", p, s);lenp = strlen(p);lens = strlen(s);printf("%d\n", kmp());} return 0;}


0 0
原创粉丝点击