1. 程式人生 > >串的匹配模式演算法

串的匹配模式演算法

        關於演算法原理,網上有很多優秀的部落格都有講解,這裡我就只記錄一下自己用程式碼實現的過程

BF演算法(c):

1.主串與模式串逐個字元進行比較,

2.出現字元不匹配時主串的比較位置重置為起始位置的下一個字元位置,模式串的比較位置重置為起始位置,

3.最終匹配成功返回主串中匹配模式串的起始位置,否則返回-1

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define MAX_SIZE 100

/**陣列長度包括 \0,字串長度不包括 \0*/

/**strlen求實際長度,sizeof求所佔空間*/

/** 定義結構體 */
typedef struct String{
    char str[MAX_SIZE];
    int length;
}String;

/** 初始化函式 */
void Init(String *Str,char str[]);
/** BF演算法實現 */
int BF(String parentString,String patternString,int index);

int main()
{
    String parentString;
    String patternString;
    int index;

    Init(&parentString,"abcdefghijklmn");
    Init(&patternString,"ghijki");

    index = BF(parentString,patternString,5);
    printf("匹配結果:%d\n",index);
    return 0;
}

void Init(String *Str,char str[])
{
    int i;
    if(strlen(str) > MAX_SIZE)
    {
        for(i = 0;i < MAX_SIZE; i++)
        {
            Str->str[i] = str[i];
        }
        Str->length =  strlen(str);
    }else{
         Str->length =  strlen(str);
         for(i = 0;i < Str->length; i++)
        {
            Str->str[i] = str[i];
        }
    }
}

int BF(String parentString,String patternString,int index)
{
    int j = 0;//字串的起始下標,index為主串的起始下標
    while(index < parentString.length && j < patternString.length){
        if(parentString.str[index] == patternString.str[j])
        {
            //一個字元匹配成功就匹配後一個,直到整個子串都匹配完
            j ++;
            index ++;
        }else{
            //匹配失敗,從第一個匹配成功的字元的後面一個字元重新開始匹配
            index = index - j + 1;
            j = 0;
        }
    }
    if(j == patternString.length)
        //匹配成功,總共匹配了patternString.length個元素,所以第一個匹配成功字元下標為index - j
        return index - patternString.length;
    else
        return -1;
}

KMP演算法:

原理部分:KMP原理

需移動的位數 = 已匹配字元位數 - 失配字元的上一位字元所對應的最大長度值

上一位字元所對應的最大長度值(用next[ ]表示):已匹配字串的字首和字尾的最長共有元素長度

比如abcac  字首:a,ab,abc,abca

                   字尾:bcac,cac,ac,c

                   最大共有元素長度為0

          。。。為了next求到淚奔。。。暫時先放下了

 

SunDay演算法(java):

public class TestSunDay {

	public static void main(String[] args) {
		
		String source = "acfdedfacfdbea";
		String target = "acfdbe";

		int i = SunDay(source.toCharArray(),target.toCharArray(),0);
		System.out.println("匹配結果:" + i);
	}
	
	/**
	 * 
	 * @param tempS 主串
	 * @param tempT 子串
	 * @param indexS 遍歷主串是從indexS下標處開始遍歷
	 * @return
	 */
	public static int SunDay(char[] tempS, char[] tempT,int indexS) {
		if(indexS >= tempS.length)
			return -1;
		//遍歷子串是從indexT下標處開始遍歷
		int indexT = 0;
		//計數匹配了多少個字元
		int count = 0;
		for (int i = indexS; i < indexS + tempT.length; i++) {
			if (tempS[i] == tempT[indexT]) {
				indexT ++;
				count ++;
			} else {
				break;
			}
		}
		//匹配的字元數和子串的長度相等,即匹配成功
		if (count == tempT.length) {
			return indexS;
		}	
		//匹配失敗,看後面一個字元在子串中有沒有相同的
		if(indexS + tempT.length < tempS.length){
			int i = check(tempS[indexS + tempT.length],tempT);
			if( i == -1){
				//沒有相同的就子串就後移子串長度個位置
				indexS += tempT.length;
				//再重新匹配
				return SunDay(tempS, tempT, indexS);
			}else{
				//後面一個字元在子串中有相同的,子串往後移若干位,使得這兩個字元對其
				indexS = indexS + tempT.length - i;
				return SunDay(tempS, tempT, indexS);
			}
		}else{
			return -1;
		}
	}

	
	/**
	 * 判斷在tempT陣列中有沒有c這個字元
	 * @param c
	 * @param tempT 
	 * @return 返回c在tempT中的下標,沒有就返回-1
	 */
	public static int check(char c, char[] tempT) {
		for (int i = 0; i < tempT.length; i++) {
			if(c == tempT[i])
				return i;
		}
		return -1;
	}
		
}