算法 | 子字符串查找=>五種算法=>strStr()函數實現

目錄

 

1、背景

2、算法介紹

3、代碼實現

3.1MP算法

3.2KMP算法

3.3Sunday算法

3.4BM算法

3.5Rabin-Karp算法


1、背景

上面是一個LeetCode的算法題:https://leetcode-cn.com/problems/implement-strstr/

2、算法介紹

  1. MP算法(爆破):遍歷所有情況
  2. KMP算法:判定如何重新開始查找(尋找對稱字符串)=>遍歷haystack(不回退)
  3. Sunday算法:判定模式指針回退位置=>遍歷haystack(不回退)
  4. BM算法:壞字符&好後綴=>從右向左遍歷
  5. Rabin-Karp算法:計算一段字符串hash與模式字符串比較,若相等帶入check()進行查找=>return true; 查找成功。否則下一個hash匹配,直到放回true。

3、代碼實現

3.1MP算法

class Solution {
public:
    int strStr(string haystack, string needle) {
        // 初始排除
        if(haystack == needle) return 0;
        int M = haystack.size();
        int N = needle.size();
        if (N == 0) return 0;
        if(N > M) return -1;
        
        // 遍歷所有情況
        for(int i = 0; i < M-N + 1;i++){
            int j;
            for(j=0;j<N;j++){
                if(haystack[i+j] != needle[j]) break;
            }
            if( j == N) return i;
        }
        return -1;
    }
};

3.2KMP算法

class Solution {
public:
    // 尋找對稱個數
     int showNext(string s, int target) {
		string str1, str2;
		int num = 0;
		bool status = false;
		for(int j = 0;j < target-1;j++){
			if(s[j] != s[j+1]){
				status = true;
				break;
			}
		}
        if(!status){
            return target - 1;
        }
        for (int i = 0; i < target / 2; i++) {
				str1 = str1 + s[i];
				str2 = s[target - i - 1] + str2;
				if (str1 == str2) {
					num = str1.size();
			}
		}	
		return num;
	}
	int strStr(string haystack, string needle) {
        // 初始排除
		if (haystack == needle) return 0;
		int target = needle.size();
		if (target == 0) return 0;
		int len = haystack.size();
		if (target > len) return -1;

		int i = 0;
		int j = 0;
		int temp;
        // KMP模式指針回退
		while (i < len && j < target) {
			if (needle[j] != haystack[i]) {
				if (i == len - 1) return -1;
				if (j == 0) {
					i++;
                    continue;
				}
                temp = showNext(needle, j);
                j = temp ? temp : 0;
			}
			else {
				if (j == target - 1) return i - j;
				i++;j++;
			}
		}
		return -1;
	}
};

3.3Sunday算法

class Solution {
public:
    // 計算偏移量 
    int calShiftMat(string s , char chr){
    	int i = -1;
       	for(int temp = 0; temp < s.size() ; temp++){
       		if(s[temp] == chr) i = temp;
       	}
        return i;
    }
    int strStr(string haystack, string needle) {
        // 初始排除
        if (haystack == needle) return 0;
		int target = needle.size();
		if (target == 0) return 0;
		int len = haystack.size();
		if (target > len) return -1;

        int i = 0;
        int j = 0;
        int temp = 0;
        while(i < len && j < target){
            if(haystack[i] != needle[j]){
                if (i == len - 1) return -1;
                if(j == 0){
                    i++;
                    continue;
                }else{
                    if(i + target - j > len) return -1;
                    temp = calShiftMat(needle,haystack[i + target - j]);
                    if(temp == -1){
                        i++;
                    }else{
                        i +=target - j - temp;
                    	j = 0;
                    }
                }
            }else{
                if (j == target - 1) return i - j;
                i++;
                j++;
            }
        }
        return -1;
    }
};

3.4BM算法

class Solution {
public:
    // 尋找模式指針回退位置
    int findChr(string needle , char chr , int j){
		for(int i=j - 1; i >= 0; i--){
			if(chr == needle[i]) return i + 1;
		}
		return 0;
	}
    //  BM算法
    int strStr(string haystack, string needle) {
        // 基本排除
		int target = needle.size();
		if (target == 0) return 0;
		int len = haystack.size();
		if (target > len) return -1;

        int i = target - 1;
        int j = target - 1;
        while(i < len && j >= 0){
            if(haystack[i] == needle[j]){
                if(j == 0) return i;
                j--;
                i--;
                continue;
            }
            if( i == len -1) return -1;
            if(findChr(needle,haystack[i],j) == 0){
	            i += target;
	            j = target - 1;
	            continue;
            }
            if(j > findChr(needle,haystack[i],j) - 1){
                i += target - findChr(needle,haystack[i],j);
                j = target - 1;
            }
        }
        return -1;
    }
};

3.5Rabin-Karp算法

class Solution {
public:
    // 計算hash 
    int hash(string key , int j , int len){
		int sum = 0;
        for(int i  = 0; i < len; i++){
            sum += key[j + i];
        }
        return sum;
	}
    // 衝突檢查
    bool check(string haystack , string needle , int address){
        for(int i = 0; i < needle.size(); i++){
            if(haystack[i + address] != needle[i]) return false;
        }
        return true;
    }
    //  Rabin-Karp算法
    int strStr(string haystack, string needle) {
        // 基本排除
        if(haystack == needle) return 0;
		int target = needle.size();
		if (target == 0) return 0;
		int len = haystack.size();
		if (target > len) return -1;

        // 模式字符串hash
        int temp = hash(needle,0,target);
        int result = 0;
        int i = 0;
        while(i < len - target + 1){
            result = hash(haystack,i,target);
            if(result == temp){
                if(check(haystack,needle,i)){
                    return i;
                }
            }
            i++;
        }
        return -1;
    }
};

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章