三、利用KMP算法进行字符串之间的匹配,先定义一个计算模式串的next数组,通过遍历模式串来记录next值和匹配长度达到记录前缀和后缀。通过KMP算法的两个指针相继往后走(不回溯),来实现模式串和文本串的匹配,结果如图3-1和3-2。
#include <stdio.h>
#include <string.h>
// 定义最大字符串长度为20
#define Max_size 20
// 定义密码组数为3
#define N 3
// 定义宏,用于表示真值
#define true 1
// 定义宏,用于表示假值
#define false -1
// 函数:计算模式串T的next数组
void Next(char *T,int *next)
{
int i = 1;// 从模式串的第二个字符开始计算next值
next[1] = 0;// 第一个字符的next值为0
int j = 0;// j用于记录匹配的长度
while(i < strlen(T) )// 遍历模式串T
{
if (j == 0 || T[i-1] == T[j-1])// 如果j为0或者当前字符匹配成功
{
i++;
j++;
next[i] = j;// 更新next值
}
else
j = next[j];// 如果不匹配,j回退到next[j]指向的位置
}
}
// 函数:KMP算法,用于在文本串S中查找模式串T
int KMP(char *S,char *T)
{
int next[Max_size];// 定义next数组
Next(T,next);//根据模式串T,初始化next数组
int i = 1;// 文本串S的指针
int j = 1;// 模式串T的指针
while (i <= strlen(S) && j <= strlen(T) )// 当两个指针都未越界时继续匹配
{
//j==0:代表模式串的第一个字符就和当前测试的字符不相等;S[i-1]==T[j-1],如果对应位置字符相等,两种情况下,指向当前测试的两个指针下标i和j都向后移
if ( j == 0 || S[i-1] == T[j-1] )// 如果j为0或者当前字符匹配成功
{
i++;
j++;
}
else// 如果不匹配,j回退到next[j]指向的位置
j = next[j];//如果测试的两个字符不相等,i不动,j变为当前测试字符串的next值
}
if(j > strlen(T) )// 如果j已经超过了模式串T的长度,说明匹配成功
{
return true;
}
else
return false;
}
int main()
{
// 定义二维数组,用于存储N组密码
char answer[N][Max_size];
for(int i = 0; i < N; i++)
{
printf("请输入初始化的第%d组密码\n",i+1);
scanf("%s",answer[i]);// 输入每组密码
}
char keys[Max_size];// 定义数组,用于存储用户输入的密码
printf("请输入密码\n");
scanf("%s",keys);// 输入用户密码
int flag = false;// 定义标志变量,用于记录是否匹配成功
for(int j = 0; j < N; j++)
{
if( KMP(keys,answer[j]) == true )// 使用KMP算法匹配密码
{
flag = true;
break;// 如果匹配成功,跳出循环
}
}
if(flag == true)
printf("密码匹配成功!");
else
printf("密码匹配失败!");
return 0;
}
![](https://img-blog.csdnimg.cn/direct/ab752edf46744827a0f747d323d813de.png)
![](https://img-blog.csdnimg.cn/direct/a0eb26c1ba0d4576b81dcebdba803c01.png)