自定义一个主串和模式串,并根据KMP算法的匹配结果,统计主串中与模式串匹配的个数,输出匹配数量及对应的匹配点位置。
前言
本代码仅供参考,萌新乱写,请大佬手下留情
一、实验目的
自定义一个主串和模式串,并根据KMP算法的匹配结果,统计主串中与模式串匹配的个数,输出匹配数量及对应的匹配点位置。
例如,主串为 abcabcabcd,子串为 bc,
则程序运行之后结果为:
匹配数量为:3,匹配点位置分别为2,5,8。
二、使用步骤
1.代码参考
代码如下:
#include <stdio.h>
#include <string.h>
//定义Next数组(含义:next[i]中元素的前i-1个字符组成的子串中的最长的相同前缀和后缀的长度再加一。)
//char* T为子串用于匹配, int* next为引用的Next数组, length表示子串T的长度
//这个next各个元素的用于记录子串中以i(当前引用到的第i的元素前的前缀与后缀相同的个数<不包含i元素本身>
//即next[1]到next[length + 1] (下标从1开始)
void Next(char* T, int* next, int Length)
{
int i = 1; //i是即子串长度,同时作为子串的指针,从子串第一个字段开始依次后移,也就是指向这个子串中的后缀的最后一个元素;
next[1] = 0;//第一个元素前无元素,定义next[1]是0
int j = 0; //j表示相同的前缀和后缀的长度,即指向子串中的前缀的最后一个元素;
while (i < Length)//下标长度小于子串长度时执行
{
//若T[i] == T[j],即表示T子串中长度为i的字符串中——长度为j+1的前缀与长度同为为j+1后缀
//若不存在,则直接进入下一次循环,比较i+1长度的字符串;
//next[i] 表示前i-1个字符组成的子串中的相等的前缀和后缀的长度再加一1
//j = 0即前缀后缀长度都为0,不进行比较,直接移到下一次循环中
if (j == 0 || T[i - 1] == T[j - 1])
{
i++;//字符串长度增加
j++;//无论是否匹配,next的下一个数都+1;
next[i] = j;
}
//若匹配失败
//重新赋予j匹配失败的前一字段的长度上+1,即表示后缀字符串相同的前缀字符串最后一个字符所在的位置
//每次匹配失败后,利用j = next[j]可以轻松找到次长前缀字符串的最后一个字符与该字符进行比较。
else
{
j = next[j];
}
}
}
//KMP算法
//S表示匹配主体字符串,T表示匹配子串
//Slen表示匹配主体字符串长度,Tlen同理
int KMP(char* S, char* T, int Slen, int Tlen, int* Size)
{
int x = 0; //用作计数器,来记录Size存储与字符串匹配的位置的数组下标
//定义匹配数组的长度(为了防止堆栈在匹配上溢出,增加匹配数组的长度)
int* next = new int[Tlen + 10];
//根据模式串T,初始化next数组
Next(T, next, Tlen + 10);
int allindex = 0;
int i = 1;
int j = 1;
while (i <= Slen) //循环条件,判断匹配字段的下标是否超过自身长度
{
//S[i-1]==T[j-1],如果对应位置字符相等,两种情况下,指向当前测试的两个指针下标i和j都向后移
if (j == 0 || S[i - 1] == T[j - 1])
{
i++;
j++;
}
else
{
j = next[j];//如果测试的两个字符不相等,i不动,j变为当前测试字符串的next值
}
// 若j(后缀长度超过自身长度),则表示匹配成功
//因为当j的长度大于匹配子串的长度时,表示j长度的子串匹配完成后,j还会再加一,所以当子串匹配完成时j的值应该是(Tlen + 1)
if (j >Tlen)
{
allindex++;
Size[x] = i - Tlen;
x++;
j = next[j];
}
}
return allindex;
}
//主函数
int main()
{
//获取输入的主串
printf("请输入需要匹配的主串:");
char A[999];
gets_s(A);
int lengthA = strlen(A);//获取字符串长度
char* a = A;
printf("\n");
//获取输入的子串
printf("请输入需要匹配的子串:");
char B[999];
gets_s(B);
int lengthB = strlen(B);//获取字符串长度
char* b = B;
printf("\n");
int* Size = new int[999];//创建匹配位置数组
int All_index = KMP(a, b, lengthA, lengthB, Size);//获取匹配总数
printf("匹配数量为:%d ,匹配点位置分别为:", All_index);
for (int i = 0; i < All_index; i++)
{
printf("%d ",Size[i]);//输出匹配的位置
}
return 0;
}
总结
作者:KUST_CZY