算法功能
若串T是串S的子串,则返回串T在串S中第一次出现的位置;否则返回-1
算法思想
首先将i, j分别指向串S和串T,如果对应位置字符相同,则比较下一个字符;如果不相同则令i=i-j+1,且j=0,又进行下一次的串T的首字节比较。一直循环下去,直到i或j指向串尾。循环结束后,若j等于串T的长度,则说明串T是串S的子串,返回其首次出现的起始位置;否则直接返回-1
核心代码
int Idx (String* S, String* T)
{
int i = 0, j = 0;
int k;
while (i < S->Len && j < T->Len)
{
if (S->ch[i] == T->ch[j])
{
i++;
j++;
}
else
{
i = i-j+1;
j = 0;
}
}
if (j == T->Len)
{
k = i-T->Len+1;
return k;
}
else
{
k = -1;
return k;
}
}
虽然算法很简单,但是第一次接触可能会有点懵,下面我们来举个例子,加深理解
过程举例
假设串S中的字符为“aabceabcdf” ,串T中的字符为"abcd"。
刚开始i=0, j=0
因为S->ch[0]和T->ch[0]相等,所以i=i+1=1,j=j+1=1
因为S->ch[1]和T->ch[1]不相等,所以i=i-j+1=1,j=0
因为S->ch[1]和T->ch[0]相等,所以i=2,j=1
相等,所以i=3, j=2
相等,所以i=4, j=3
不相等,所以i= i+j-1=2, j=0
以此类推下去…
直到i=9, j=4,因为此时j的值与串T的长度相等,所以退出循环,k就等于6,返回k的值
上面的例子是关于串T是串S的子串的情况,还有另一种情况,即串T不是串S的子串,读者可以举个例子,尝试自己动手写出推理过程,可以更好地掌握这个算法噢
源代码
# include <stdio.h>
# define MAX 100
typedef struct
{
int Len;
//字符串的长度
char ch[MAX];
//字符数组
}String;
int Idx (String* S, String* T)
{
int i = 0, j = 0;
int k;
while (i < S->Len && j < T->Len)
{
if (S->ch[i] == T->ch[j])
{
i++;
j++;
}
else
{
i = i-j+1;
j = 0;
}
}
if (j == T->Len)
{
k = i-T->Len+1;
return k;
}
else
{
k = -1;
return k;
}
}
int main ()
{
int k;
String S, T;
printf ("请输入串S中的字符:");
gets (S.ch);
printf ("请输入串S的长度:");
scanf ("%d", &S.Len);
getchar ();
//吸收回车键
printf ("请输入串T中的字符:");
gets (T.ch);
printf ("请输入串T的长度:");
scanf ("%d", &T.Len);
k = Idx (&S, &T);
if (k == -1)
{
printf ("\n串T不是串S的子串!!!");
}
else
{
printf ("\n串T为串S的子串,第一次出现的位置为:%d", k);
}
}