返回目录:
Chilan Yu:《数据结构》目录链接zhuanlan.zhihu.com【问题描述】
KMP算法是字符串模式匹配算法中较为高效的算法之一,其在某次子串匹配母串失败时并未回溯母串的指针而是将子串的指针移动到相应的位置。
【输入形式】
3组字符串,每组字符串占一行。每行包含由空格分隔的两个字符串,字符串仅由英文小写字母组成且长度不大于100。
【输出形式】
每组数据输出1行,输出后一个字符串在前一个字符串中的位置,如果不匹配,则输出0。
【样例输入】
string str
thisisalongstring isa
nosubstring subt
【样例输出】
1
5
0
【提示】
表示字符串的数据结构可以是字符数组或用串类实现。
KMP算法调用很简单,但难的是理解算法的思想。掌握算法的思想才能说是掌握算法。
#include <iostream>
#include <string.h>
using namespace std;
int * buildNext( char * P )
{ //构造模式串P的next表(改进版本)
int m = strlen(P), j = 0; //“主”串指针
int * N = new int[m]; //next表
int t = N[0] = -1; //模式串指针
while( j<m-1 )
{
if( 0>t || P[j]==P[t] ) //匹配
{
j++;t++;
N[j] = ( P[j]!=P[t] ? t : N[t] );
}
else //失配
t = N[t];
}
return N;
}
int match( char * P, char * T )
{ //KMP算法
int * next = buildNext(P); //构造next表
int n = (int)strlen(T), i = 0; //文本串指针
int m = (int)strlen(P), j = 0; //模式串指针
while( j<m && i<n ) //自左向右逐个比对字符
if( 0>j || T[i]==P[j] ) //若匹配,或P已移出最左侧(两个判断的次序不可交换)
{ i++; j++; }
else
j = next[j]; //模式串右移(注意:文本串不用回退)
delete [] next; //释放next表
return i-j;
}
int main()
{
char * P, * T;
P = new char[100];
T = new char[100];
int i=3;
int ans;
while( i-- )
{
cin >> T >> P;
ans = match(P,T)+1;
if( (ans-1)>=(int)strlen(T) ) ans = 0;
cout << ans << endl;
}
return 0;
}