KMP匹配字符

229 阅读2分钟
#define OK 1
#define ERROR 0
#define TRUE 1
#define FALSE 0
#define MAXSIZE 100 /* 存储空间初始分配量 */

typedef int Status;        /* Status是函数的类型,其值是函数结果状态代码,如OK等 */
typedef int ElemType;    /* ElemType类型根据实际情况而定,这里假设为int */
typedef char String[MAXSIZE+1]; /*  0号单元存放串的长度 */
//生成一个串
Status StrAssign(String T,char *chars){
    
    int i;
    if (strlen(chars)>MAXSIZE) {
        return ERROR;
    }else{
        T[0] = strlen(chars);
        for ( i=1; i<=T[0]; i++) {
            T[i] = *(chars + i -1);
        }

        return OK;
    }

}
//清空一个串
Status ClearString(String S){
    S[0] = 0;
    return OK;
}
//输出串
void StrPrint(String T){
    for (int i=1; i<=T[0]; i++) {
        printf("%c",T[i]);
    }
    printf("\n");
}
//返回串的长度
int SStrLength(String S)
{
    return S[0];
}
//KMP模式串匹配算法1
void get_next(String T,int *next){
    int i,j;
    j = 1;
    i = 0;
    next[1] = 0;
    while (j<T[0]) {
        if (i==0 || T[i] == T[j]) {
//            T[i]表示后缀的单个字符
//            T[j]表示前缀的单个字符
            ++i;
            ++j;
            next[j] = i;
        }else{
            i = next[i];
        }
    }
}
//输入next数组
void NextPrint(int next[],int length){
    for (int i=1; i<=length; i++) {
        printf("%d",next[i]);
    }
    printf("\n");
}
int count = 0;
//KMP匹配算法1
int Index_KMP(String S,String T,int pos){
    //i 是主串S当前位置的下标,j是模式串T当前位置的下标
    int i = pos;
    int j = 0;
    //定义一个空的next数组
    int next[MAXSIZE];
    //对T串进行分析,得到next数组
    get_next(T, next);
    
    count = 0;
    //如果i小于S的长度,j小于T的长度
    while (i<=S[0] && j<=T[0]) {
        //如果两字母相等,则继续,j++,i++
        if (j==0 || S[i] == T[j]) {
            i++;
            j++;
        }else{
            //如果不匹配时,j回退到合适的位置,i值不变
            j = next[j];
        }

    }
    if (j>T[0]) {
        return i-T[0];
    }
    
    return -1;
}

//KMP模式串匹配算法2
void get_nextVal(String T,int *nextVal){
    int i,j;
    j = 1;
    i = 0;
    nextVal[1] = 0;
    while (j<T[0]) {
        if (i==0 ||T[i] == T[j]) {
            ++i;
            ++j;
            //如果当前字符与前缀不同,则当前的j为nextVal在i的位置的值
            if (T[i] != T[j]) {
                nextVal[j] = i;
            }else{
                //如果当前字符与前缀相同,则将前缀的nextVal值赋给nextVal在i的位置
                nextVal[j] = nextVal[i];
            }

        }else{
            i = nextVal[i];
        }

    }

}
//KPM匹配算法2
int Index_KMP2(String S,String T,int pos){
    //i是主串S的下标,j 是模式串T的下标
    int i = pos;
    int j = 1;
    int next[MAXSIZE];
    //得到回退数组
    get_nextVal(T, next);
    //遍历
    while (i<=S[0] && j<=T[0]) {
        //如果两个字符相等则继续,j++,i++
        if (j==0 || S[i] == T[j]) {
            i++;
            j++;
        }else{
            //如果不匹配,j回退到相应位置,i不变
            j = next[j];
        }

    }
    if (j>T[0]) {
        return i-T[0];
    }


    return -1;
}