复习的时候又看了以前写的文,然后真想一棍子打死自己。。。next数组居然还是char型http://t.csdn.cn/ubT0C,下面是刚修改的。
代码(从1开始时)
//数组第一个位置存储长度
int *getNext(char *a)
{
int len = a[0];
int *next= (int *)malloc(sizeof(int)*len);
int k=0,j=1;
next[1]=0;
while(len>j)//j是当前检查元素的前缀的最后一个元素的下标
{
//如果a[j]==a[k]说明最大前后缀长度可以加一
if(k==0||a[j]==a[k]) next[++j]=++k;//k初始值0是next[1]=0
else k = next[k];//如果某一个位置不再匹配最大前后缀,则刚才的最大前后缀就断了,回去再匹配(注意这时j并不移位)
}
}
int KMP(char *str,char *chapter)
{
int *next = getNext(chapter);
int len2 = chapter[0],len1 = str[0];
int i=1,j=1;//i用来做str下标索引,j为next下标索引
while(i<len1&&j<len2)
{
if(str[i]==chapter[j])
{
i++;
j++;
}
else j = next[j];
}
if(j==len2)return i-1;
return 0;//0是存放数组长度的单元,成功匹配不会返回0
}
代码(从0开始时)
题目没什么要求就用这种吧,0开始的话就不用输入数据第一位是数字后面位是字符了,可以直接用C的string。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int *getNext(char *chapter)
{
int len = (int)strlen(chapter);
int i=-1,j=0;
int *next = (int *)malloc(sizeof(int)*len);
next[0]=-1;
while(j<len-1)//写len就会数组越界,因为判断里是j,而循环体操作的是(j+1)
{
if(i==-1||chapter[i]==chapter[j]) next[++j]=++i;
else i=next[i];
}
return next;
}
int strStr(char *str,char *chapter)
{
int *next = getNext(chapter);
int len1 = (int)strlen(str),len2 = (int)strlen(chapter);
int i=0,j=0;
while(i<len1 && j<len2)
{
if(j==-1||str[i]==chapter[j])//如果能滑到j==-1的位置,则说明str[i]就是和chapter[0]也不匹配,所以str[i]继续下滑,与chapter[0]比较
{
i++;j++;
}
else j=next[j];
}
if(len2==j)return i-len2;
return -1;
}
int main()
{
char *chapter = "abcaababc",*str = "aabcbabcaabcaababc";
int k = strStr(str,chapter);
printf("%d",k);
return 0;
}
测试
28. 找出字符串中第一个匹配项的下标 - 力扣(LeetCode)把代码放到力扣上试了试,准确运行。