字符储存在1~length的位置上
简单模式匹配
思路:从主串的第一个位置起和模式串的第一个字符开始比较,如果相等,则继续逐一比较后续字符;否则从主串的第二个字符开始,再重新用上一步的方法与模式串中的字符做比较,以此类推,直到比较完模式串中的所有字符。若匹配成功,则返回模式串在主串中的位置;若匹配不成功,则返回一个可区别于主串所有位置的标记,如“0”。
int index(Str str,Str substr)
{
int i = 1,j = 1,k = 1;//串从数组下标1位置开始存储,初值为1
while(i <= str.length && j <= substr.length)
{
if(str.ch[i] == substr[j])
{
i++;
j++;
}
else
{
j = 1;
i = ++k;//匹配失败,i从主串的下一个位置开始匹配,k储存了主串上一次的起始位置
}
}
if(j > substr.length)
return k;
else ruturn 0;
}
主串(ABABCABCACBAB)和模式串(ABCAC)匹配过程
KMP算法
设主串为s1s2…sn,模式串为p1p2…pm,在上面的匹配过程中,经常出现一个关键状态(表2),其中i和j分别为主串和模式串中当前参与比较的两个字符的下标。
模式串的前部某子串P1P2…Pj-1与主串中的一个子串Si-j+1Si-j+2…Si-1匹配,而Pj与Si不匹配。每当出现这种状态时,简单模式匹配算法的做法是:一律将i赋值为i-j+2,j赋值为1,重新开始比较。这个过程反映到表2中可以形象地表示为模式串先向后移动一个位置,然后从第一个字符P1开始逐个和当前主串中对应的字符做比较;当再次发现不匹配时,重复上述过程。这样做的目的是试图消除Si处的不匹配,进而开始Si+1及其以后字符的比较,使得整个过程得以推进下去。
如果在模式串后移的过程中又出现了其前部某子串P1P2…与主串中某子串…Si-2Si-1相匹配的状态,则认为这是一个进步的状态。因为通过模式串后移排除了一些不可能匹配的状态,来到了一个新的局部匹配状态,并且此时Si有了和模式串中对应字符匹配的可能性。为了方便表述,记表中描述的状态为Sk,此处的新状态为Sk+1,此时可以将简单模式匹配过程看成一个由Sk向Sk+1推进的过程。当由Sk来到Sk+1时有两种情况可能发生:其一,S处的不匹配被解决,从si+1继续往下比较,若来到新的不匹配字符位置,则模式串后移寻找状态Sk+2;其二,Si处的不匹配仍然存在,则模式串继续后移寻找状态Sk+2如此进行下去,直到得到最终结果。
说明:为了使上边其一与其二的表述看起来清晰工整且抓住重点,此处省略了对匹配成功与失败这两种容易理解的情况的描述。
说明:模式串后移使P1移动到Si+1,即模式串整个移过Si的情况也认为是Si处的不匹配被解决。试想,如果在匹配过程中可以省略掉模式串逐渐后移的过程,而从Sk直接跳到Sk+1,则可以大大提高匹配效率。带着这个想法,我们把Sk+1状态添加到表2中得到表3。