데이터 구조의 문자열 패턴 일치 알고리즘 (KMP)
참조 코드 의 사이트 주소
여기 서 나 는 나의 생각 을 정리 해 보 겠 다.
먼저 기본 개념 을 소개 하 다
아래 약속
우 리 는 next 배열 의 첫 번 째 위치 값 이 0 이 라 고 약속 합 니 다. 모드 문자열 의 첫 번 째 문자 가 일치 하지 않 는 다 는 것 을 의미 합 니 다. 이때 메 인 문자열 의 현재 일치 하지 않 는 문자 의 다음 문자 부터 다시 일치 합 니 다 (i 증가 1). 모드 문자열 도 물론 처음부터 시작 합 니 다 (j 는 1).
위 에 표 시 된 패턴 문자열 의 접두사 길 이 는 k - 1 인 문자열 과 j 에서 k - 1 길 이 를 앞 세 는 문자열 이 같 습 니 다.
이때 두 가지 상황 이 발생 한다.
첫 번 째: T [k] = T [j]
그래서 'T [1]... T [k] =' T [j - k + 1]... T [j] 는 'T [1]... T [1]' = 'T [j - k + 1]... T [j - 1]' 때 next [j] = k 그래서 'T [1]... T [k] =' T [j - k + 1]... T [j] '때 next [j + 1] = k + 1 = next [j] + 1
만약 S [i]! =T [j], 패턴 문자열 의 j 번 째 문자 가 어 울 리 지 않 으 면 우 리 는 S [i] 와 T [next [j] 를 비교 하 게 할 것 이다. 그러나 우 리 는 첫 번 째 상황 인 T [next [j] = = T [j] 이기 때문에 당연히 S [i] 와 같 지 않다. 이것 은 한 번 의 헛 된 일 을 한 것 과 같다.
그래서 위의 판단 에 하나의 판단 을 더 해 야 한다. 만약 에 T [k + 1] = T [j + 1] 라면 next [j + 1] = next [k + 1], 그렇지 않 으 면 next [j + 1] = k + 1
여기 서 예 를 들 어 모드 꼬치 ABAB 는 k 가 첫 번 째 위치 A 를 가리 키 고 j 가 세 번 째 위치 A 를 가리 키 면 둘 이 똑 같 습 니 다. 원래 next [j + 1] = 2 를 직접 할당 하 였 으 나 T [k + 1] = T [j + 1] 때문에 next [j + 1] = next [k + 1] = 1 로 바 꾸 었 습 니 다.원래 ABAB 의 next 배열 은 0112 였 으 나 지금 은 0101 로 바 뀌 었 다.
두 번 째: T [k]! =T[j]
예 를 들 어 모드 문자열 abacdababc, 그 중 k 는 4, j 는 9 입 니 다.각각 캡 처 해 보면 abac 와 abab 입 니 다.
왜냐하면: T [k]! =T [j] 는 abac 의 앞 에 있 는 a 와 abab 의 꼴찌 두 번 째 a 가 같 으 면 abac 의 두 번 째 b 부터 비교 할 수 있 음 을 알 수 있 습 니 다. 그래서 여 기 는 k 를 2 즉 k = next [k] 로 바 꾸 고 abac 의 두 번 째 와 abab 의 마지막 요 소 를 비교 하면 됩 니 다.다시 T [k] 와 비교 하면 T [j + 1] = next [k] + 1;그렇지 않 으 면 j = next [j] 를 j = next [1] = 0 까지 다시 실행 합 니 다. 이렇게 T [j + 1] = next [1] + 1 = 1
요약 하면:
수학의 정리 처럼 한 걸음 한 걸음 밀 어 낼 수 있 기 때문에 공식 으로 생각 하거나 이미지 기억 으로 바 꿔 도 된다.
상술 한 분석 을 종합 하면 절차 적 사고방식 을 얻어 낼 수 있다
개선 전과 개선 후의 c 언어 코드 를 드 리 겠 습 니 다.
개선 전 코드
void get_next(SString T, int next[]){
int j = 1;
int k = 0;
next[1] = 0;
while(j<T[0]){
if(k==0 || T[j]==T[i]){
j++;
k++;
next[j] = k;
}else{
k = next[k];
}
}
return;
}
개 선 된 후의
void get_nextval(SString T, int nextval[]){
int j = 1;
int k = 0;
next[1] = 0;
while(j<T[0]){
if(k==0 || T[k]==T[j]){
j++;
k++;
if(T[k]!=T[j]){
nextval[j] = k;
}else{
nextval[j] = nextval[k];
}
}else{
k = next[k];
}
}
return;
}
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
로그'메타프로그램 루비 버전 2'3장 읽기동적 방법 Object#send 호출 방법은 약간 메모와 Object#send obj.send(:my_method, 3) Object#send를 사용하면 어떤 방법으로든 호출할 수 있습니다. privete 방법을 호...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.