I - Oulipo
思路:
首先确定好模式串和文本串,对模式串处理,得到nex[]数组,即可确定最大子字符串的长度;
当然我们要清楚,KMP()的作用和原理;
原理即始终遵循nex[i]所在的下标值,表示前i个字符串与后i个字符串相同;
例如:str[9]=" abababc";str[6]='b';
nex依次对应:nex[1~8]:0 0 1 2 3 4 0
nex[6]=4:"在ababab"中指前4个字符串:”abab“ 与后四个“abab”相同;
然后就是两个字符串进行比较,注意输入字符串的起始下标和比较时,两者的下标
方法一:C
#include <stdio.h>
#include <string.h>
int nex[10005];
char str1[1000005],str2[10005];
int cnt;
void Get(int len2)
{
int j=0;
memset(nex,0,sizeof(nex));//清除
nex[1]=j;
for(int i=2;i<=len2;i++)
{
while(j&&str2[j+1]!=str2[i])
j=nex[j];
if(str2[j+1]==str2[i]) j++;
nex[i]=j;
}
}
void kmp(int len1,int len2)
{
int i=1,j=0;//str1输入的起始坐标是1,注意j=0;难得试出来啦!!
Get(len2);
for(i=1;i<=len1;i++)
{
while(j&&str1[i]!=str2[j+1]) j=nex[j];
if(str1[i]==str2[j+1]) j++;
if(j==len2)//找完一个完整的子字符串时,开始改变j的值!!!!
{
cnt++;
j=nex[j];//千万别忘记
}
}
}
int main()
{
int n;
int len1,len2;
scanf("%d",&n);
getchar();
while(n--)
{
gets(str2+1);
gets(str1+1);
len1 = strlen(str1+1);
len2 = strlen(str2+1);
cnt = 0;
kmp(len1,len2);
printf("%d\n",cnt);
}
return 0;
}方法二:C
#include <stdio.h>
#include <string.h>
int nex[10005];
char str1[1000005],str2[10005];
int cnt;
void Get(int len2)
{
memset(nex,0,sizeof(nex));//清零!!
int i = 0,j = -1;
nex[0] = -1;
while (i<len2)
{
if(j == -1 || str2[i] == str2[j])
{
i++,j++;
if (str2[i]!=str2[j])
nex[i] = j;
else
nex[i] = nex[j];
}
else
j=nex[j];
}
// for(int i=0;i<=len2;i++)
// printf("%d ",nex[i]);
// printf("\n");
}
void kmp(int len1,int len2)
{
int i=0,j=0;//注意i=0,j=0!!!
Get(len2);
while(i<len1)
{
if(j==-1||str1[i]==str2[j])
++i,++j;
else
j=nex[j];
// printf("j:%d ",j);
if(j == len2)
{
cnt++;
j = nex[j];
}
}
// printf("\n");
}
int main()
{
int n;
int len1,len2;
scanf("%d",&n);
getchar();//一定要吃回车!!!
while(n--)
{
gets(str2);
gets(str1);
len1 = strlen(str1);
len2 = strlen(str2);
cnt = 0;
kmp(len1,len2);
printf("%d\n",cnt);
}
return 0;
}多次测试!!结果依然是输入翻了车!!下次一定要记得检测输入!!!
本文深入讲解KMP算法的实现原理及应用,通过两种C语言实现方式对比,详细介绍了如何求解模式串的最大子字符串长度,并利用KMP算法进行字符串匹配。
4188

被折叠的 条评论
为什么被折叠?



