KMP算法

来源:互联网 发布:淘宝改差评的链接 编辑:程序博客网 时间:2024/06/09 23:33

ACM模版

非常规KMP

KMP_Pre

/* * next[]的含义,x[i - next[i]...i - 1] = x[0...next[i] - 1] * next[i]为满足x[i - z...i - 1] = x[0...z - 1]的最大z值(就是x的自身匹配) * 字符串从下标0开始存,最后得到的next数组比常规情况对应每位少1 * ex: ababaaaba:常规:011234223;非常规:-100123112 */void KMP_Pre(char x[], int m, int next[]){    int i, j;    j = next[0] = -1;    i = 0;    while (i < m)    {        while (-1 != j && x[i] != x[j])        {            j = next[j];        }        next[++i] = ++j;    }    return ;}

preKMP

/* * kmpNext[]的意思:next'[i] = next[next[...[next[i]]]] * (直到next'[i] < 0或者x[next'[i]] != x[i]) * 这样的预处理可以快一些  * 字符串从下标0开始存,最后得到的next数组比常规情况对应每位少1 * ex: ababaaaba:常规:011234223;非常规:-100123112 */void preKMP(char x[], int m, int kmpNext[]){    int i, j;    j = kmpNext[0] = -1;    i = 0;    while (i < m)    {        while (-1 != j && x[i] != x[j])        {            j = kmpNext[j];        }        if (x[++i] == x[++j])        {            kmpNext[i] = kmpNext[j];        }        else        {            kmpNext[i] = j;        }    }    return ;}

KMP_Count

/* * 此函数与上述两个函数中的任意一个搭配使用(即调用上述两个函数中的任意一个) * 返回x在y中出现的次数,可以重叠 */int next[10010];int KMP_Count(char x[], int m, char y[], int n){    //x是模式串,y是主串    int i, j;    int ans = 0;    //preKMP(x, m, next);    KMP_Pre(x, m, next);    i = j = 0;    while (i < n)    {        while (-1 != j && y[i] != x[j])        {            j = next[j];        }        i++, j++;        if (j >= m)        {            ans++;            j = next[j];        }    }    return ans;}

常规KMP

getNext

/* * 通过计算返回子串Tnext数组 * 串从下标1开始存,下标为0的地址存串长度,即T[0]表示串T的长度 */void getNext(std::string T, int *next){    int i = 1, j = 0;    next[1] = 0;    while (i < T[0])    //此处T[0]表示串T的长度    {        if (j == 0 || T[i] == T[j])        {            next[++i] = ++j;        }        else        {            j = next[j];    //若字符不相同,则j值回溯        }    }    return ;}

indexKMP

/* * 返回子串T在主串S中第pos个字符之后的位置。若不存在,则函数返回值为0 * T非空,1 ≤ pos ≤ StrLength(S) */int indexKMP(std::string S, std::string T, int pos){    int i = pos;    //用于主串S当前位置下标值,若pos不为1,则从pos位置开始匹配    int j = 1;      //j用于子串T中当前位置下标值    int next[255];  //定义next数组    getNext(T, next);   //对串T作分析,得到next数组    while (i <= S[0] && j <= T[0])  //若i小于S的长度且j小于T的长度时循环继续    {        if (j == 0 || S[i] == T[j]) //两字母相等则继续,与朴素算法相比增加了j = 0判断        {            i++;            j++;        }        else                        //指针后退重新开始匹配        {            j = next[j];            //j退回合适的位置,i值不变        }    }    if (j > T[0])    {        return i - T[0];    }    else    {        return 0;    }}

修正于2017.3.23 非常规KMP indexKMP部分14行修正!!!S[i] == T[i] X => S[i] == T[j]

感谢评论区 xiaonuo911teamo 大神的悉心指导!!!

0 0
原创粉丝点击