임기 말에 데이터 구조를 검토하기 위해 내 자신의 통찰력과 이해의 일부를 적어 두었습니다. 우선, 내 자신의 요구 사항에서 나는 내 코드에서 간결하고 명확하게 노력하고 어려운 곳에 주석을 달 것입니다.
기사 디렉토리
문자열 매칭: BF 매칭 과정 및 구현, KMP에서 패턴 문자열의 다음 값 계산 및 매칭 과정, KMP에서 개선된 패턴 문자열 nextval
팁: 다음은 이 글의 본문이며, 아래 사례는 참고용입니다(c++).
BF 알고리즘
가장 좋은 경우의 시간복잡도는 O(n+m), n은 메인 문자열의 길이, m은 부분 문자열의 길이, 최악의 경우의 시간
복잡도는 O(n*m)이다.
코드는 다음과 같습니다(예제).
//暴力匹配算法
//需要传入主串,匹配位置,模式串(要匹配的串)
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;//匹配成功
}
다음은 고전적인 사용 시나리오입니다.
이 알고리즘을 사용하는 것은 주로 기본 문자열에서 패턴 문자열의 모든 위치를 가져오는 것이므로 기본 문자열을 완전히 작동하려면 루프가 필요합니다.
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;
}
BF클래식 알고리즘은
길지만 사용하기가 매우 편리하며 메인 문자열, 패턴 문자열, 초기 매칭 위치만 전달하면 첫 번째 패턴 문자열의 위치를 반환할 수 있다.
//这个算法只能返回一个位置
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 알고리즘
코드는 다음과 같습니다
. unsigned, 즉 음수가 아닌 숫자, 이 유형은 int보다 하나 더 많은 이진수를 저장할 수 있습니다. 즉, 모든 이진 비트는 정보를 저장하는 데 사용되며 데이터가 양수인지 여부를 판단하는 부호 비트가 없습니다. 부정적인)
다음 배열의 흥미로운 값은 패턴 문자열과만 관련이 있습니다.
//得到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
패턴 문자열과 메인 문자열 사이의 쓸모없는 매칭을 줄이기 위해 개선된 다음 솔루션 방법
//改进的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];
}
}
결론: 리뷰 후 이해가 되었고, 기사를 읽는 것이 주로 기억하기 쉬움