串是由零个或多个字符组成的有限序列,又称为字符串。
串中的字符数目称为串的长度。
零个字符的串称为空串,它的长度为零。
空格串,是只包含空格的串。空格串是有内容有长度的,而且可以不止是一个空格。
子串与主串,串中任意个数的连续字符组成的子序列称为该串的子串,相应地,包含子串的串称为主串。
子串在主串中的位置就是子串的第一个字符在主串中的序号。
串的比较是通过组成串的字符之间的编码来进行的,而字符的编码指的是字符在对应字符集中的序号。
串的基本操作和线性表有很大差别,线性表更关注的是单个元素的操作,串中更多的是查找子串位置,得到指定位置子串、替换子串等操作。
一般用定长数组来存储串的,可以将实际的串长度值保持在数组的0下标位置。
子串的定位操作通常称为串的模式匹配,应该算是串中最重要的操作之一。
朴素的模式匹配算法:
int Index(String S, String T, int pos)
{
int i = pos;
int j = 1;
while (i <= S[0] && j <= T[0])
{
if (S[i] == T[j])
{
++i;
++j;
}
else
{
i = i - j + 2;
j = 1;
}
}
if (j > T[0])
return i - T[0];
return 0;
}
KMP算法,可以大大避免重复遍历的情况:
void get_next(String T, int *next)
{
int i, j;
i = 1;
j = 0;
next[1] = 0;
while (i < T[0])
{
if (j == 0 || T[i] == T[j])
{
++i;
++j;
next[i] = j;
}
else
j = next[j];
}
}
int Index_KMP(String S, String T, int pos)
{
int i = pos;
int j = 1;
int next[255];
get_next(T, next);
while (i <= S[0] && j <= T[0])
{
if (j == 0 || S[i] == T[j])
{
++i;
++j;
}
else
j = next[j];
}
if (j > T[0])
return i - T[0];
return 0;
}
KMP算法改进:
void get_nextval(String T, int *nextval)
{
int i, j;
i = 1;
j = 0;
nextval[1] = 0;
while (i < T[0])
{
if (j == 0 || T[i] == T[j])
{
++i;
++j;
if (T[i] != T[j])
nextval[i] = j;
else
nextval[i] = nextval[j];
}
else
j = nextval[j];
}
}