串的基本操作:
假设有一个顺序串定义如下:
#define MAXSIZE 100
typedef struct
{
char ch[MAXSIZE];
int len;
}seqstr;
seqstr* S;
1.串的连接运算:
seqstr* Strcat(seqstr* s, seqstr* t)
{
int i;
seqstr* r;
printf("s = %s,t = %s\n", s->ch, t->ch);
if ((s->len + t->len) > MAXSIZE)printf("上溢\n");
else
{
for (i = 0; i < s->len; i++)r->ch[i] = s->ch[i];
for (i = 0; i < t->len; i++)r->ch[s->len + i] = t->ch[i];
r->ch[s->len + i] = '\0';
r->len = s->len + t->len;
}
printf("r = %s\n", r->ch);
return r;
}//最后生成的串r为s+t的结果
2.求子串运算:
seqstr* Substr(seqstr* s, int i, int j)
{
int k;
seqstr* t;
printf("s = %s\n",s->ch);
if (i + j - 1 > s->len)printf("超界\n");
else
{
for (k = 0; k < j; k++)t->ch[k] = s->ch[i + k - 1];
t->len = j;
t->ch[t->len] = '\0';
}
printf("t = %s\n",t->ch);
return t;
}
3.子串定位(串的模式匹配):
在串 s 中找出一个与串 t 相同的子串,一般把串s成为目标,把串 t 成为模式,若在目标 s 中找到模式t则模式匹配成功,找不到则模式匹配失败。
朴素的模式匹配算法
int Index(seqstr* s, seqstr* t)
{
int i = 1, j = 1;
while ((i <= s->len) && (j <= t->len))
{
if (s->ch[i - 1] == t->ch[j - 1])
{
i++; j++;
}
else
{
i = i - j + 2; j = 1;
}
}
if (j > t->len)return (i - t->len);//匹配成功
else return -1;//匹配失败
}
时间复杂度的分析:
1.最好的情况,每次不成功的匹配都发生在 t 的第一个字符与 s 中的字符的比较时,设从 s 的第 i 个字符开始匹配,成功的概率为 pi,则在之前一共比较了(i-1)次。若在第i趟成功的匹配中匹配了 m 次,则总的比较次数为(i-1+m)次。
∑pi(i-1+m) = [1/(n-m+1)]∑(i-1+m) = 1/2(n+m) ( i 的取值从1 到 n-m+1)
由此,最好情况下算法的平均时间复杂度为O(n+m)
2.最坏的情况,每一次不成功的匹配都发生在t的最后一个字符与s中相应字符的比较时,新一趟的起始位置为 i-m+2,若在第i趟匹配成功,则在之前一共匹配了(i-1)趟,每趟m次,再加上第i次的比较,一共比较了(im)次。
∑pi(im) = m/(n-m+1)∑i = (m/(n-m+1)× 1/2 ×(n-m+1)×(n-m+2) = m(n-m+2)/2
由于n>>m,最坏情况下算法的时间复杂度为O(m×n)
链式存储结构下的模式匹配算法:
linkstr* Index(linkstr* s, linkstr* t)
{
linkstr* first, * sr, * er;
first = s;
sr = first; er = t;
while (sr && er)
{
if (sr->data == er->data)
{
sr = sr->next;
er = er->next;
}
else
{
first = first->next;
sr = first;
er = t;
}
}
if (er == NULL)return(first);
else return NULL;
}
关于改进的模式匹配算法
当一趟匹配过程中出现字符比较不相等时,不再回溯 i 值,而是利用部分匹配的结果将模式向右移一段距离后,继续进行比较。
这样算法的时间复杂度为O(n+m)。
void GetNext(seqstr* t, int next[])
{
int j, k;
j = 1, k = 0;
next[1] = 0;
while (j < t->len)
{
if ((k == 0) || (t->ch[j - 1] == t->ch[k - 1]))
{
j++; k++; next[j] = k;
}
else k = next[k];
}return;
}//得到模式串t的值,并存入数组
int Index(seqstr* s, seqstr* t)
{
int i = 1, j = 1;
while ((i <= s->len) && (j <= t->len))
{
if ((j == 0) || (s->ch[i - 1] == t->ch[j - 1]))
{
i++; j++;
}
else j = next[j];
}
if (j < t->len)return(i - t->len);
else return -1;
}