• kmp处理题型总结


    1.求出T(模板串)对S(原串)的最小完全匹配位置  HDU-1711 Number Sequence (普通kmp)

    2.求T(模板串)在S(原串)中出现的次数(可以重复匹配)  POJ-3461 Oulipo (kmp修改)

    3.求T(模板串)在S(原串)出现的次数(不可重复匹配)HDU-2087 剪花布条

    4.求字符串S的最小的循环节 HDU-3746 Cyclic Nacklace   ,HDU-1358 Period (KMP循环节问题)  ,POJ-2406 Power Strings 

    5.找到(输出)字符串S中所有的 公共前后缀 部分 POJ-2752 Seek the Name, Seek the Fame (KMP)

    5*.输出 字符串S中所有的 公共前后缀串之和 HDU-3336 Count the string (KMP)

    6.找出所给的多个串的相同子串部分 POJ-3080 Blue Jeans (KMP优化匹配)

    7.给出两个字符串a,b然后求a前缀与b后缀的最长公共部分 并输出 长度 HDU-2594 Simpsons’ Hidden Talents (kmp) 也可以说是 (扩展kmp)

    模板总结:

    求某个字符串的next数组 (对于kmp而言)

    const int maxn = 1e5+7;
    int
    nex[maxn];char str[maxn]; void getnext(char *str){ int i=0,j=-1; int len = strlen(str); nex[i]=j; while(i<len){ if(j==-1||str[i]==str[j]){ i++;j++; nex[i]=j; } else j=nex[j]; } }

    KMP 求最小位置匹配,以及否出现判断(没有出现输出返回-1):

    int nex[maxn];
    char str[maxn];//文本串
    char str1[maxn];//模式串
    int kmp(){
        int i = 0, j = 0;
        getnext(str1);
        int len = strlen(str);
        int len1 = strlen(str1);
        while(i < len && j < len1)
        {
            if(j == -1 || a[i] == b[j])
            {
                i++; 
                j++;
            }
            else j = nex[j];
        }
        return (j==len1)?(i -len1 + 1):-1;
    }

    KMP 求匹配次数

    int nex[maxn];
    char str[maxn];//文本串
    char str1[maxn];//模式串
    int kmp(char *str, char *str1){
        int ans = 0;
        int i = 0,j = 0;
        int len,len1;
        len = strlen(str),len1 = strlen(str1);
        if(len == 1 && len1 == 1){
           return  (str[0] == str1[0]) ? 1 : 0;
        }
        getnext(str1);
        for(i=0;i<len;i++){
            while( j>0 && str[i]!=str1[j] ){
                j=nex[j];
            }
            if(str[i] == str1[j]) j++;
            if(j==len1){
                ans++;
                j=nex[j];//重复统计次数
           //j = 0;不重复统计次数 } }
    return ans; }

    KMP 求循环节个数(如果不存在则返回-1)

    int loop(char *str){
        int len = strlen(str);
        //nex[len] == 0时必然没有循环节
        if(nex[len]!=0){
            //循环节长度
            int k = len - nex[len];
            //如果循环节个数不为0
            if(!(len % k)){
                //求出循环节个数
                int num = len / k;
                return num;
            }
        }
        else return -1;
    }

    计算某个字符串的所有前缀子串,在字符串出现的次数的总和

    例如 s: "abab"

    The prefixes are: "a", "ab", "aba", "abab"

    The sum = 2 + 2 + 1 + 1 = 6.

    //(1)求所有前缀和
    int len = strlen(str);//母串
    for(int i=1;i<=len;i++){ dp[i]=dp[nex[i]]+1; sum = (sum+dp[i])%mod; }

    //(2)回溯 找到所有公共的前缀部分
    ans = nex[nex[i]];

    求扩展KMP的 extend[]数组:

    //str2为模板串,str1为原串(母串)
    void
    getnext(char *str2){ nex[0]=len2; int j=0,p; while(j+1<len1&&str2[j]==str2[j+1])j++; nex[1]=j; int k=1; for(int i=2;i<len2;i++){ p=nex[k]+k-1; if(i+nex[i-k]-1<p) nex[i]=nex[i-k]; else{ j = max(0,p-i+1); while(i+j<len2&&str2[i+j]==str2[j])j++; nex[i]=j; k=i; } } } void exkmp(char *str1,char *str2){ getnext(); int j=0,p; int len = min(len1,len2); while(j<len&&str2[j]==str1[j])j++; extend[0]=j; int k=0; for(int i=1;i<len1;i++){ p = extend[k]+k-1; if(i+nex[i-k]-1<p) extend[i]=nex[i-k]; else{ j=max(0,p-i+1); while(i+j<len1&&j<len1&&str1[i+j]==str2[j])j++; extend[i]=j; k=i; } } }
  • 相关阅读:
    js正则匹配
    包含HTML的字符串去掉HTML标签
    smart-table 服务端请求真分
    禁用H5 表单验证novalidate
    webpack
    linux 进程查看及杀死进程
    配置ca服务器和http,mail加密
    mysql权限
    mysql查询
    mysql储存引擎
  • 原文地址:https://www.cnblogs.com/Tianwell/p/11249345.html
Copyright © 2020-2023  润新知