朴素模式匹配
串的模式匹配指的是子串在主串中的定位匹配,例如主串A = “abcdef”,子串B = “cd”,那么子串与主串的第三、四位相同。
思路:
(1)首先应该让主串的第一位与子串的第一位对比,相等则对比第二位,否则子串向后移一位,子串第一位与主串第二位对比。
(2)子串的第一位依次与主串的第1-5位匹配对比。
/****************************************\
*输入:char Fat[]--主串,char Son[]--子串
*输出:无
*返回:匹配成功的位置,不成功则返回-1
\****************************************/
int Index(char Fat[], char Son[])
{
int i = 0;
int j = 0;
int FLen = strlen(Fat);//获取主串和子串的长度
int SLen = strlen(Son);
while ((i < FLen) && (j < SLen)) //当子串和主串均未匹配完
{
if (Fat[i] == Son[j]) //当前字符相同,则匹配下一位字符
{
i++;
j++;
}
else
{
/*当前字符不相同,下一个应该匹配的应该是,上次主串匹配的
下一位字符i-j+2(上次主串匹配的前一个字符位置:i-j)。
子串下次匹配应该重新是第0位*/
i = i - j + 2;
j = 0;
}
}
// 匹配结束,如果子串匹配完最后一位,则匹配成功。
//否则,此时是主串已经全部匹配完,没有找到相同的部分,匹配失败
if (j == SLen)
{
return (i - j);
}
else
{
return -1;
}
}
KMP模式匹配
KMP模式匹配,主要是分析子串的字符相似度,减少没有必要的匹配。
例如主串A = “abcdefg”,子串B = “abcx”,在d
与x
匹配失败后,没有必要从主串的b,c
开始匹配了,因为前三位匹配成功,但子串b,c
均不与首字符相同,则主串相应位置也不会相同。
另一种是子串相似度较高的情况,例如主串A = “abababc”,子串B = “ababc”,在第一次匹配失败后,不需要再从主串的第1,2,3位开始匹配,而是直接对主串的第4位a
和子串的第2位a
进行匹配。
因为子串B的第0-1字符与2-3字符相同,且子串B与主串A前4个字符相等,那么主串A的2-3字符自然与子串B的0-1字符相等,只要从主串的第4位和子串的第2位开始比较即可。
匹配时,主串的匹配位置是不回溯的,而子串的匹配位置是会回溯的,因此用next数组表示对应的位置匹配失败时,回溯的位置。
数学表达式如下:
n e x t [ j ] = { − 1 j = 0 M a x { k ∣ 0 < k < j , B [