KMP算法

KMP算法

        KMP算法求出ex[i]数组,ex[i]数组表示主串S中以第i个字符(也即S[i-1]位置)为尾字符的后缀与模式串T的前缀的最长公共部分。

        KMP模板中,字符都是从下标0开始存放的,直到m-1位置。假设有两个串S和T,其中T为模板串,S为主串。KMP其实本质是用来看S中每个i位置的后缀最多能与T的多长的前缀匹配的算法。即前缀匹配后缀的算法。进行模式串匹配只是KMP的一个附加结果。

        其实求得的f[i]==x表示i位置的模式串T的0到i-1字符的后缀能与模式串T的0到x-1字符匹配。即当T[i]与S[j]不匹配的时候,就取用T[f[i]]==T[x]与S[j]匹配看看是否能匹配。

MP与KMP模板如下:

/*************************MP模板****************************/
char T[1000];//待匹配串
char P[100];//模板串

//失配指针,记住这里f要比P多一位
//因为P到m-1即可,但是f还要计算出m的失配指针
int f[101];

void find(char *T, char *P, int *f) //找到所有匹配点
{
    int n = strlen(T);
    int m = strlen(P);
    int j = 0;
    for(int i = 0; i < n; i++)
    {
        while(j && T[i] != P[j]) j = f[j];
        if(T[i] == P[j]) j++;
        if(j == m) printf("%d\n", i - m + 1);//就算j到m了,也用f[m]继续匹配
    }
}
void getFail(char *P, int *f)
{
    int m = strlen(P);
    f[0] = f[1] = 0;
    for(int i = 1; i < m; i++)//虽然字符串是0到m-1,但是要求出f[m]的值
    {
        int j = f[i];
        while(j && P[i] != P[j]) j = f[j];
        f[i + 1] = P[i] == P[j] ? j + 1 : 0;
    }
}
/*************************MP模板****************************/


/*************************KMP模板****************************/
char T[1000];//待匹配串
char P[100];//模板串
int f[101];//优化后的失配指针,记住这里f要比P多一位,因为P到m-1即可,但是f还要计算出m的失配指针
int f2[101];//f2用来保存KM指针,是为优化f的失配指针,f保存的是优化之后的失配指针
void find(char *T, char *P, int *f) //找到所有匹配点
{
    int n = strlen(T);
    int m = strlen(P);
    int j = 0;
    for(int i = 0; i < n; i++)
    {
        while(j && T[i] != P[j]) j = f[j];
        if(T[i] == P[j]) j++;
        if(j == m) printf("%d\n", i - m + 1);
    }
}
void getFail(char *P, int *f)
{
    int m = strlen(P);
    f[0] = f[1] = 0;
    f2[0]=f2[1]=0;
    for(int i = 1; i < m; i++)
    {
        int j = f2[i];
        while(j && P[i] != P[j] ) j = f2[j];
        f2[i+1] = f[i + 1] = (P[i] == P[j]) ? j + 1 : 0;

        //既然i+1的失配位置指向j+1,但是P[i+1]和P[j+1]的内容是相同的
        //所以就算指针从i+1跳到j+1去,还是不能匹配,所以f[i+1]直接=f[j+1]
        if(f[i+1]==j+1 && P[i+1]==P[j+1]) f[i+1]=f[j+1];
    }
}
/*************************KMP模板****************************/


KMP模板题

POJ 3461Oulipo(KMP:统计一个串出现的次数):KMP模板题。解题报告!

HDU 1711Number Sequence(KMP:找模板第一次出现的位置):KMP模板题。解题报告!

HDU 3336Count the string(KMP:串前缀匹配自身+DP):简单的前缀匹配+DP问题。解题报告!

POJ3080 Blue Jeans(KMP:最长连续公共子序列):求多个字符串的最长公共连续子串,如果存在多个长度相同的就输出字典序最小的那个。解题报告!

POJ3450 Corporate Identity(KMP:最长连续公共子序列):类似于上一题。解题报告!

HDU2087剪花布条(KMP:贪心):需要贪心的从左到右有考虑。解题报告!

HDU2203亲和串(KMP:循环移位):给你串T和串P问你串P是否能和T循环移K位后的串匹配。解题报告!

HDU1867 A + B for you again(KMP:后缀与前缀):字符串合并。解题报告!

 

KMP前缀与后缀

HDU 2594Simpsons’ HiddenTalents(KMP:后缀与前缀):KMP的思想。解题报告!

POJ 2752Seek the Name, Seekthe Fame(KMP:后缀与前缀):找出所有前缀与后缀匹配的长度。解题报告!

 

 

求字符串最短循环节

UVA 1328Period(KMP:最短循环节):如何求字符串的循环节?解题报告!

POJ 2406Power Strings(KMP:找串循环节):求出最小循环节个数。解题报告!

HDU 3746Cyclic Nacklace(KMP:补齐循环节):要你补充完整一个串,使得该串有循环节构成。解题报告!

POJ 2185Milking Grid(KMP:循环节加强版):转换思维。解题报告!

 

 

 

 

 

 

  • 3
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 9
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 9
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值