字符串匹配算法 : 1.BF算法 2.RK算法

282 阅读3分钟

去除重复字母 给你一个仅包含小写字母的字符串,请你去除字符串中重复的字母,使得每个字母只出现一次。需保证返回结果的字典序最小且不能打乱其他字符的相对位置(字典序即在英文字典中单词的排序规则) 示例: 输入:“bcabc” 输出:“abc”

输入:“cbacdcbc” 输出:“acdb”

思路: ①简单特殊情况判断,字符串为空; ②数组record记录字母出现的次数; ③利用字符栈stack(连续数组)存储去除重复字符的结果,利用栈来找到正确次序; ④遍历字符串,判断当前字符是否已经存入栈中,若已经存在,对record数组相应的位置进行’- -’, 表示栈里已经有这个字符没有必要重复存储; ⑤若不存在,通过while循环找到正确位置: ①. 栈不能为空; ②. 栈顶元素大于当前字符; ③. 栈顶字符对应的record的记录次数不能大于1. ⑥入栈。

char* removeDuplicateLetter(char *s) {

    // boundary detect
    if(s == NULL || strlen(s) == 0) return "";
    if(strlen(s) == 1) return s;

    // array to record the count of appearance of letters
    char record[26] = {0};
    int len = (int)strlen(s);
    
    // stack
    char* stack = malloc(len * sizeof(char));
    int top = -1; // stack top pointer
    
    // record the count for every char in the string
    for(int i = 0; i < len; i++) {
        record[s[i] - 'a']++;
    }
    
    // use stack to process the string to get the result
    for(int i = 0; i < len; i++) {
        
        //check is this char already inside the stack
        int isExsisting = 0;
        for(int j = 0; j < top; j++) {
            
            if(s[i] == stack[j]) {
                isExsisting = 1;
                break;
            }
            
        }
        
        if(isExsisting ==  1) {
            record[s[i] - 'a'] --;
        } else {
            
            while (top > -1 && stack[top] >= s[i] && record[stack[top] - 'a'] > 1) {
                record[stack[top] - 'a'] --;
                top --;
            }
            
            top ++;
            stack[top] = s[i];
            
        }
        
    }
    
    printf("the top pointer is %d\n", top);
    return stack;
}

字符串匹配算法 题目:有一个主串S = {a, b, c, a, c, a, b, d, c}, 模式串T = {a, b, d}; 请找到模式串在主串中第一次出现的位置,字母均为小写;

①BF算法 暴力解法,一个一个的比较,算法容易理解但是效率低下

typedef char String[MAXSIZE+1];
/* 生成一个其值等于chars的串T */
Status StrAssign(String T,char *chars)
{
    int i;
    if(strlen(chars)>MAXSIZE)
        return ERROR;
    else
    {
        T[0]=strlen(chars); // the first element save the length of the string
        for(i=1;i<=T[0];i++)
            T[i]=*(chars+i-1);
        return OK;
    }
}

int Index_BF(String S, String T) {
    
    // main string index
    int i = 1;
    
    // model string index
    int j = 1;
    
    while (i <= S[0] && j <= T[0]) {
        
        if (S[i] == T[j]) {
            i ++;
            j ++;
        } else {
            i = i - j + 2;
            j = 1;
        }
        
    }
    
    if (j > T[0]) {
        return i - T[0];
    } else {
        return -1;
    }
}

②RK算法 求解主串的各个子串和模式串的哈希值,通过比较哈希值来找位置, 通过对比数字而不是对比字母来提高效率

int Index_RK(char* S, char* T) {
    
    // hash value unit
    int d = 26;
    
    // the length of S and T
    int m = (int)strlen(S);
    int n = (int)strlen(T);
    
    // get d^max
    int maxD = 1;
    for(int i = 0; i < n - 1; i++) {
        maxD = maxD*d;
    }
    
    unsigned int A = 0; // hash value for T
    unsigned int ST = 0; // hash value for subString of S
    
    // get the hash value for T and first subString of S
    for(int i = 0; i != n; i++) {
        A = (d*A + (T[i] - 'a'));
        ST = (d*ST + (S[i] - 'a'));
    }
    
    // compare has value of T and subString of S
    for(int i = 0; i <= m-n; i++) {
        
        if (A == ST) {
            // in case of hash conflict, here we can check is the result correct before we return the index
            return i;
        } else {
            ST = d * (ST - (S[i] - 'a') * maxD) + (S[i + n] - 'a');
        }
        
    }
    
    return -1;
}