Zeichenfolgenabgleich ----- BF-Algorithmus und KMP-Algorithmus

Für die Überprüfung der Datenstruktur am Ende des Semesters habe ich einige meiner eigenen Erkenntnisse und Erkenntnisse aufgeschrieben. Zunächst einmal bemühe ich mich aufgrund meiner eigenen Anforderungen, in meinem Code prägnant und klar zu sein, und werde an schwierigen Stellen Kommentare abgeben.


String-Matching: BF-Matching-Prozess und -Implementierung, Berechnung und Matching-Prozess des nächsten Werts des Muster-Strings in KMP, verbessertes Muster-String nextval in KMP


Tipp: Das Folgende ist der Text dieses Artikels, und der folgende Fall dient als Referenz (c++)

Ein BF-Algorithmus

Die Zeitkomplexität ist im besten Fall O(n+m), n ist die Länge des Hauptstrings und m ist die Länge des Teilstrings, die Zeitkomplexität im schlechtesten Fall ist O(n*m
).

Der Code lautet wie folgt (Beispiel):

//暴力匹配算法
//需要传入主串,匹配位置,模式串(要匹配的串)
bool BF(string S,int pos,string T) {
    
    
	//直接对主串的pos位置到pos+模式串的长度考试匹配,只要有一处不等就直接返回false
	for (int i = 0; i < T.length();i++) {
    
    
		if (T[i]!=S[pos+i]) {
    
    
			return false;//匹配失败
		}
	}
	return true;//匹配成功
}

Als nächstes folgt das klassische Verwendungsszenario:
Die Verwendung dieses Algorithmus dient hauptsächlich dazu, alle Positionen der Musterzeichenfolge in der Hauptzeichenfolge zu erhalten, sodass eine Schleife benötigt wird, um die Hauptzeichenfolge vollständig zu betreiben.

int main() {
    
    
	string s = "12341234567651日2任然";
	string s1 = "12";
	//输出主串中模式串所在的位置,
	//主串最后不足模式串的长度的部分没有意思,因为一定不会存在想要的答案
	//说实话,为了使用一个函数而写一个循环,我觉得这样有违写函数的目的,函数就是为了将操作变成一行
	for (int i = 0; i < s.length()-s1.length();i++) {
    
    
		if (BF(s,i,s1)) {
    
    
			cout << i<<" ";
		}
	}
	//结果0 4
	return 0;
}

Obwohl der klassische BF-Algorithmus
lang ist, ist er sehr bequem zu verwenden. Sie müssen nur die Hauptzeichenfolge, die Musterzeichenfolge und die anfängliche Übereinstimmungsposition übergeben, und die Position der ersten Musterzeichenfolge kann zurückgegeben werden.

//这个算法只能返回一个位置
int BF(string S,string T,int pos) {
    
    
	int i = pos, j = 0;
	while (i < S.length()&&j<T.length()) {
    
    //两串均为比较到串尾
		if (S[i]==T[j]) {
    
    
			i++; j++;
		}else {
    
    
			i = i - j + 1;//位置后移
			pos = i;//更新pos的位置
			j = 0;
		}
	}
	if (j == T.length()) return pos;
	else return -1;//没有找到返回-1
}

2. KMP-Algorithmus

Der Code sieht wie folgt aus (Beispiel):
Das von mir im folgenden Code verwendete unsigned (unsigned Bit) kann durch int ersetzt werden. Der Grund, warum ich dies mache, ist, Warnungen zu reduzieren (kleines Wissen: der Typ ist die Länge des Strings unsigned, also eine nicht negative Zahl, this Der Typ kann eine Binärzahl mehr speichern als int, das heißt, alle Binärbits werden zum Speichern von Informationen verwendet, und es gibt kein Vorzeichenbit, um zu beurteilen, ob die Daten positiv sind oder Negativ)

Der interessante Wert des nächsten Arrays bezieht sich nur auf die Musterzeichenfolge.

//得到next数组
void get_next(int next[],string T) {
    
    
	next[1] = 0; next[2] = 1;
	unsigned i = 2, j = 1;//这里的i和j都代表数学位置,所以在下面的对串的所以的使用要-1
	while (i <= T.length()) {
    
    
		//如果两个位置的字符相等就让i后面一个位置等于j+1
		if (j==0||T[i-1]==T[j-1]) {
    
    
			i++, j++;
			next[i] = j;//i和j都已自加
		}else {
    
    
			j = next[j];
		}
	}
}

//这个返回的是数学位置,不是索引,可以在返回的最后的-1即可
int KMP(string S,string T) {
    
    
	unsigned i = 1, j = 1;
	static int next[10];
	get_next(next,T);
	while (i<=S.length()&&j<=T.length()) {
    
    
		if (j==0||S[i-1]==T[j-1]){
    
    
			i++, j++;
		}
		else {
    
    
			j = next[j];
		}
	}
	if (j>T.length())return i - T.length()//返回数学位置
	else return -1;
}

int main() {
    
    
	string s = "1233414322";
	string s1 = "233";
	cout << KMP(s,s1);
	return 0;
}
//结果为2

Verbesserte nächste Lösungsmethode, um nutzlose Übereinstimmungen zwischen Musterzeichenfolge und Hauptzeichenfolge zu reduzieren

//改进的next求解方法
//计算next的修正值
void get_nextval(string T, int nextval[]) {
    
    
	int i = 1, j = 0;
	while (i < T.length()) {
    
    
		if (j == 0 || T[i] == T[j]) {
    
    
			i++, j++;
			if (T[i] != T[j]) nextval[i] = j;
			else nextval[i] = nextval[j];
		}else j = nextval[j];
	}
}

Fazit: Kann ich nach der Rezension verstehen, und das Lesen des Artikels ist hauptsächlich gut zu merken

Je suppose que tu aimes

Origine blog.csdn.net/blastospore/article/details/122050330
conseillé
Classement