串的匹配方式
串的朴素匹配方式
#include<stdio.h>
#include<string.h>
int index (char * s , char * t )
{
int i ,j ;
for (i = 0 ; i < strlen(s) ; i ++)
{
if (s[i] == t[0]){
for (j = 0 ; j < strlen(t); j ++ , i ++)
{
if (s[i] != t[j]) break;
}
if (j == strlen(t)) return i - j;
else i = i - j + 1;
}
}
return -1;
}
int main(void)
{
return 0;
}
KMP
next 数组的推导
- 只和模式串有关系,与主串没有关系
- j指针的回溯与模式串的性质同样有关系
- 储存的值为0代表一号位置与主串不匹配的位置匹配
- 1代表1号位置与主串不匹配的位置匹配,依次类推
朴素版next数组推导
void get_next (char * t , int * next)
{
int i , j;//i为串的不匹配位置的指针, j为匹配最长前后缀的指针
i = 1;
j = 0;
next[1] = 0;
while (i < strlen(t))
{
if (j == 0 || t[i] == t[j]){
i ++;
j ++;
next[i] = j;
}
else {
j = next[j];
//此处j指针回溯,同样利用的串的性质,当时第j位不匹配时,j指针回溯
}
}
}
优化版next数组推导
优化后是为了防止一连串的字符重复回溯
void get_next (char * t , int * next)
{
int i , j;//i为串的不匹配位置的指针, j为匹配最长前后缀的指针
i = 1;
j = 0;
next[1] = 0;
while (i < strlen(t))
{
if (j == 0 || t[i] == t[j]){
i ++;
j ++;
if (t[i] != t[j]) next[i] = j;
else next[i] = next[j];
//此处为修改的代码
}
else {
j = next[j];
//此处j指针回溯,同样利用的串的性质,当时第j位不匹配时,j指针回溯
}
}
}
KMP算法的实现
#include<stdio.h>
#include<string.h>
void get_next (char * t , int * next)
{
int i , j;//i为串的不匹配位置的指针, j为匹配最长前后缀的指针
i = 1;
j = 0;
next[1] = 0;
while (i < strlen(t))
{
if (j == 0 || t[i] == t[j]){
i ++;
j ++;
if (t[i] != t[j]) next[i] = j;
else next[i] = next[j];
}
else {
j = next[j];
//此处j指针回溯,同样利用的串的性质,当时第j位不匹配时,j指针回溯
}
}
}
int KMP (char *s , char * t , int pos)
{
//pos 为从主串的pos位置开始匹配
int i = pos , j = 1;
int next[255] = {0};
get_next(t , next);
//for (i = 1 ; i <= 5 ; i ++)
//{
// printf("%d--",next[i]);
//}
//puts("");
while (i <= strlen(s + 1) && j <= strlen(t + 1))
{
if (j == 0 || s[i] == t[j])
{
++ i;
++ j;
}
else {
j = next[j];
}
}
if (j > strlen(t + 1)){
return i - strlen(t + 1);
}
else return 0;
}
int main(void)
{
char a[50], b[30];
int x;
scanf("%s %s",a + 1 , b + 1);
printf("%d %d\n",strlen(a+1) , strlen(b + 1));
printf("%d\n",KMP(a , b , 1));
return 0;
}