💡 【习题集】 ▼04 串

This commit is contained in:
康建伟
2018-01-17 12:54:23 +08:00
parent a906c77077
commit aebcb047db
25 changed files with 1842 additions and 0 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 KiB

View File

@@ -0,0 +1,36 @@
#include <stdio.h>
#include "../../../▲课本算法实现/▲04 串/01 SequenceString/SequenceString.c"//**▲04 串**//
/* 函数原型 */
void Algo_4_10(SString T, SString S);
int main(int argc, char *argv[])
{
char *s = "0123456789";
SString T, S;
printf("逆置前T = ");
StrAssign_Sq(T, s);
StrPrint_Sq(T);
printf("\n\n");
printf("逆置后S = ");
Algo_4_10(T, S);
StrPrint_Sq(S);
printf("\n\n");
return 0;
}
/*━━━━━━━━━┓
┃题4.10将T逆置为S┃
┗━━━━━━━━━*/
void Algo_4_10(SString T, SString S)
{
int i;
for(i=T[0]; i>=1; i--)
S[T[0]-i+1] = T[i];
S[0] = T[0];
}

View File

@@ -0,0 +1,67 @@
#include <stdio.h>
#include "../../../▲课本算法实现/▲04 串/01 SequenceString/SequenceString.c"//**▲04 串**//
/* 函数原型 */
void Algo_4_11(SString R, SString S, SString T, int a[]);
int main(int argc, char *argv[])
{
int a[MAXSTRLEN+1];
char *s = "amdhcjgfdlpinbefcopgkqikeb";
char *t = "mhjlpinopkqik";
SString T, S, R;
int i;
printf("初始化S和T...\n");
StrAssign_Sq(S, s);
StrAssign_Sq(T, t);
printf("\n");
printf("S = ");
StrPrint_Sq(S);
printf("\n");
printf("T = ");
StrPrint_Sq(T);
printf("\n\n");
Algo_4_11(R, S, T, a);
printf("R = ");
StrPrint_Sq(R);
printf("\n");
printf("a = ");
for(i=1; i<=a[0]; i++)
printf("%d ", a[i]);
printf("\n\n");
return 0;
}
/*━━━━━━━━┓
┃题4.11r=s-s∩t┃
┗━━━━━━━━*/
void Algo_4_11(SString R, SString S, SString T, int a[]) //数组a的0号存储a中元素个数
{
int i, p;
SString Tmp;
StrAssign_Sq(R, "");
Tmp[0] = 1;
for(i=1,a[0]=0; i<=S[0]; i++)
{
Tmp[1] = S[i]; //把S[i]变为串
p = Index_Sq_1(T, Tmp, 1); //判断S[i]是否在T中
if(!p)
p = Index_Sq_1(R, Tmp, 1); //判断S[i]是否已出现过
if(!p)
{
a[0]++;
a[a[0]] = i;
StrInsert_Sq(R, a[0], Tmp);
}
}
}

View File

@@ -0,0 +1,47 @@
#include <stdio.h>
#include "../../../▲课本算法实现/▲01 绪论/Status.h" //**▲01 绪论**//
#include "../../../▲课本算法实现/▲04 串/01 SequenceString/SequenceString.c"//**▲04 串**//
/* 函数原型 */
Status Algo_4_12(SString S, SString T, SString V);
int main(int argc, char *argv[])
{
char *s = "----***--*-**-****-*****-----";
char *t = "**";
char *v = "^";
SString T, S, V;
printf("替换前...\n");
StrAssign_Sq(S, s);
StrAssign_Sq(T, t);
StrAssign_Sq(V, v);
printf("S = ");
StrPrint_Sq(S);
printf("\n");
printf("T = ");
StrPrint_Sq(T);
printf("\n");
printf("V = ");
StrPrint_Sq(V);
printf("\n\n");
printf("替换后...\n");
printf("S = ");
Algo_4_12(S, T, V);
StrPrint_Sq(S);
printf("\n\n");
return 0;
}
/*━━━━━━━━━┓
┃题4.12:字符串替换┃
┗━━━━━━━━━*/
Status Algo_4_12(SString S, SString T, SString V)
{
if(Replace_Sq(S, T, V)) //已定义
return OK;
else
return ERROR;
}

View File

@@ -0,0 +1,41 @@
#include <stdio.h>
#include "../../../▲课本算法实现/▲04 串/01 SequenceString/SequenceString.c"//**▲04 串**//
/* 函数原型 */
void Algo_4_13(SString S, SString T);
int main(int argc, char *argv[])
{
char *s = "----***--*-**-****-*****-----";
char *t = "**";
SString T, S;
printf("删除前...\n");
StrAssign_Sq(S, s);
StrAssign_Sq(T, t);
printf("S = ");
StrPrint_Sq(S);
printf("\n");
printf("T = ");
StrPrint_Sq(T);
printf("\n\n");
printf("删除后...\n");
printf("S = ");
Algo_4_13(S, T);
StrPrint_Sq(S);
printf("\n\n");
return 0;
}
/*━━━━━━━━━━━┓
┃题4.13删除S中包含的T┃
┗━━━━━━━━━━━*/
void Algo_4_13(SString S, SString T)
{
int i;
for(i=1; i=Index_Sq_1(S, T, 1); i++)
StrDelete_Sq(S, i, T[0]);
}

View File

@@ -0,0 +1,137 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include "../../../▲课本算法实现/▲01 绪论/Status.h" //**▲01 绪论**//
#include "../../../▲课本算法实现/▲02 线性表/01 SequenceList/SequenceList.c" //**▲02 线性表**//
#include "../../../▲课本算法实现/▲04 串/01 SequenceString/SequenceString.c" //**▲04 串**//
/* 宏定义 */
#define STACK_INIT_SIZE 100 //顺序栈存储空间的初始分配量
#define STACKINCREMENT 10 //顺序栈存储空间的分配增量
/* 类型定义 */
typedef SString SElemType; //栈元素类型为字符串数组
typedef struct //栈结构类型
{
SElemType *base; //在栈构造之前和销毁之后base的值为NULL
SElemType *top; //栈顶指针
int stacksize; //当前已分配的存储空间,以元素为单位
}SqStack;
/* 函数原型 */
Status InitStack_4_14(SqStack *S); //字符串栈的初始化
Status Push_4_14(SqStack *S, SElemType e); //入栈
Status Pop_4_14(SqStack *S, SElemType *e); //出栈
Status Algo_4_14(SqList P, SString Str);
int main(int argc, char *argv[])
{
char *p = "-+a*bc/de"; //后缀abc*+de/-
int i;
SqList P;
SString Str;
InitList_Sq(&P);
for(i=1; i<=strlen(p); i++)
ListInsert_Sq(&P, i, p[i-1]);
printf("前缀表达式P = ");
for(i=0; i<P.length; i++)
printf("%c", P.elem[i]);
printf("\n\n");
Algo_4_14(P, Str);
printf("后缀表达式Str = ");
StrPrint_Sq(Str);
printf("\n\n");
return 0;
}
/*━━━━━━━━━━━┓
┃题4.14:前缀式变后缀式┃
┗━━━━━━━━━━━*/
/* 假设表达式变量均为单字符 */
Status Algo_4_14(SqList P, SString Str)
{
int i;
SElemType e1, e2, tmp;
SqStack S;
InitStack_4_14(&S);
for(i=P.length-1; i>=0; i--) //从后往前读取
{
tmp[0] = 1;
tmp[1] = P.elem[i];
if(isalpha(P.elem[i])) //遇到变量入栈
Push_4_14(&S, tmp);
else
{
Pop_4_14(&S, &e1); //遇到操作符连续出栈
Pop_4_14(&S, &e2);
Concat_Sq(e1, e1, e2); //将出栈的两个变量与操作符正确连接
Concat_Sq(e1, e1, tmp);
Push_4_14(&S, e1); //连接好的字符串入栈
}
}
Pop_4_14(&S, &tmp); //弹出转换完成后的字符串
StrCopy_Sq(Str, tmp);
if(S.base==S.top) //最后栈应该为空
return OK;
else
return ERROR;
}
Status InitStack_4_14(SqStack *S)
{
(*S).base = (SElemType*)malloc(STACK_INIT_SIZE*sizeof(SElemType));
if(!(*S).base)
exit(OVERFLOW);
(*S).top = (*S).base;
(*S).stacksize = STACK_INIT_SIZE;
return OK;
}
Status Push_4_14(SqStack *S, SElemType e)
{
int i;
if((*S).top-(*S).base>=(*S).stacksize) //栈满,追加存储空间
{
(*S).base = (SElemType *)realloc((*S).base, ((*S).stacksize+STACKINCREMENT)*sizeof(SElemType));
if(!(*S).base)
exit(OVERFLOW); //存储分配失败
(*S).top = (*S).base + (*S).stacksize;
(*S).stacksize += STACKINCREMENT;
}
for(i=0; i<=e[0]; i++)
(*(S->top))[i] = e[i]; //进栈先赋值,栈顶指针再自增
(S->top)++;
return OK;
}
Status Pop_4_14(SqStack *S, SElemType *e)
{
int i;
if((*S).top==(*S).base)
return ERROR;
(*S).top--; //出栈栈顶指针先递减,再赋值
for(i=0; i<=(*((*S).top))[0]; i++)
(*e)[i] = (*((*S).top))[i];
return OK;
}

View File

@@ -0,0 +1,156 @@
#include <stdio.h>
#include "../../../▲课本算法实现/▲01 绪论/Status.h" //**▲01 绪论**//
#include "../../../▲课本算法实现/▲04 串/01 SequenceString/SequenceString.c" //**▲04 串**//
/* 函数原型 */
Status Algo_4_15(SString T, char *chars);
int Algo_4_16(SString S, SString T);
Status Algo_4_17(SString S, SString T, SString V);
int main(int argc, char *argv[])
{
char *t = "ab**c*de***fg";
char *s = "ab**c*de***fh";
int i;
SString T, S, M1, M2;
printf("███题 4.15 验证...███\n");
Algo_4_15(T, t);
Algo_4_15(S, s);
printf("T = ");
StrPrint_Sq(T);
printf("\n");
printf("S = ");
StrPrint_Sq(S);
printf("\n\n");
printf("███题 4.16 验证...███\n");
i = Algo_4_16(S, T);
if(i>0)
printf("S > T\n");
else if(i<0)
printf("S < T\n");
else
printf("S == T\n");
printf("\n");
printf("███题 4.17 验证...███\n");
Algo_4_15(M1, "**");
Algo_4_15(M2, "^");
Algo_4_17(S, M1, M2);
printf("\"^\" 替换 \"**\"S = ");
StrPrint_Sq(S);
printf("\n\n");
return 0;
}
/*━━━━━━━━━┓
┃题4.15:字符串赋值┃
┗━━━━━━━━━*/
Status Algo_4_15(SString T, char *chars)
{
int i, len;
len = strlen(chars);
if(len>MAXSTRLEN) //chars过长
return ERROR;
else
{
T[0] = len;
for(i=1; i<=len; i++)
T[i] = chars[i-1]; //chars为常量
return OK;
}
}
/*━━━━━━━━━┓
┃题4.16:字符串比较┃
┗━━━━━━━━━*/
int Algo_4_16(SString S, SString T)
{
int i = 1;
while(i<=S[0] && i<=T[0])
{
if(S[i]==T[i])
i++;
else
return S[i] - T[i];
}
return S[0] - T[0];
}
/*━━━━━━━━━┓
┃题4.17:字符串替换┃
┗━━━━━━━━━*/
Status Algo_4_17(SString S, SString T, SString V)
{
int count = 1; //count遍历S
int i, j, k;
SString Tmp_beh;
i = count;
j = 1;
while(i>=1 && i<=S[0] && j<=T[0]) //寻找第一个匹配的位置
{
if(S[i]==T[j])
{
i++;
j++;
}
else
{
i = i - (j-1) +1; //j-1代表徒劳地前进了j-1个位置
j = 1;
}
}
if(j>T[0] && T[0]!=0) //T不为空串
count = i-T[0]; //匹配成功
else
count = 0;
while(S[0]-T[0]+V[0]<=MAXSTRLEN && count!=0) //有匹配的字符串且可以被完全替换
{
Tmp_beh[0] = S[0]-i+1; //摘取S中匹配字符串之后的字符到Tmp_beh
for(k=1; k<=S[0]-i+1; k++)
Tmp_beh[k] = S[k+i-1];
S[0] = S[0]-T[0]+V[0];
for(k=1; k<=V[0]; k++) //联接V到S上
S[k+count-1] = V[k];
for(k=count+V[0]; k<=S[0]; k++) //联接取自S中的后半部分到S上
S[k] = Tmp_beh[k-count-V[0]+1];
count += V[0]; //i切换到下一个位置
i = count;
j = 1;
while(i>=1 && i<=S[0] && j<=T[0]) //定位下一个匹配的字符串
{
if(S[i]==T[j])
{
i++;
j++;
}
else
{
i = i - (j-1) +1; //j-1代表徒劳地前进了j-1个位置
j = 1;
}
}
if(j>T[0] && T[0]!=0) //T不为空串
count = i-T[0]; //匹配成功
else
count = 0;
}
if(count==0) //S中的T已全部被替换
return OK;
else //S中尚有T但是V已经插不进去了
return ERROR;
}

View File

@@ -0,0 +1,48 @@
#include <stdio.h>
#include "../../../▲课本算法实现/▲01 绪论/Status.h" //**▲01 绪论**//
#include "../../../▲课本算法实现/▲04 串/01 SequenceString/SequenceString.c" //**▲04 串**//
/* 函数原型 */
void Algo_4_18(SString S, int total[]);
int main(int argc, char *argv[])
{
char *s = "dbasydujhge638940[gptokljrsehgadcsbnmv,c.b'ng[p098437eywdghswqdecxvghju";
SString S;
int total[128] = {};
int i;
StrAssign_Sq(S, s);
printf("S = ");
StrPrint_Sq(S);
printf("\n\n");
Algo_4_18(S, total);
printf(" S 中不同的字符共计 %d 个:\n", total[0]);
for(i=1; i<=127; i++)
{
if(total[i]!=0)
printf("字符 \'%c\' 有 %d 个.\n", i, total[i]);
}
printf("统计完毕...\n");
printf("\n");
return 0;
}
/*━━━━━━━━━━━━━━━━━━━━━━━━┓
┃题4.18:统计字符串中不同字符总数和每种字符的个数┃
┗━━━━━━━━━━━━━━━━━━━━━━━━*/
/* 利用字符与数字对应的特性 */
void Algo_4_18(SString S, int total[]) //total长度设为128代表各种不同字符
{
int i;
for(i=1; i<=S[0]; i++) //字符串中间无空字符
{
if(!total[S[i]]) //此处无字符
total[0]++; //不同字符总数
total[S[i]]++; //各种字符个数
}
}

View File

@@ -0,0 +1,83 @@
#include <stdio.h>
#include "../../../▲课本算法实现/▲04 串/01 SequenceString/SequenceString.c"//**▲04 串**//
/* 函数原型 */
void Algo_4_19(SString R, SString S, SString T, int a[]);
int main(int argc, char *argv[])
{
int a[MAXSTRLEN+1];
char *s = "amdhcjgfdlpinbefcopgkqikeb";
char *t = "mhjlpinopkqik";
SString T, S, R;
int i;
printf("初始化S和T...\n");
StrAssign_Sq(S, s);
StrAssign_Sq(T, t);
printf("\n");
printf("S = ");
StrPrint_Sq(S);
printf("\n");
printf("T = ");
StrPrint_Sq(T);
printf("\n\n");
Algo_4_19(R, S, T, a);
printf("R = ");
StrPrint_Sq(R);
printf("\n");
printf("a = ");
for(i=1; i<=a[0]; i++)
printf("%d ", a[i]);
printf("\n\n");
return 0;
}
/*━━━━━━━━┓
┃题4.19r=s-s∩t┃
┗━━━━━━━━*/
void Algo_4_19(SString R, SString S, SString T, int a[]) //数组a的0号存储a中元素个数
{
int i, j, k;
int flag;
a[0] = 0;
R[0] = 0; //初始化R
for(i=1; i<=S[0]; i++)
{
flag = 0;
for(j=1; j<=T[0]; j++)
{
if(S[i]==T[j])
{
flag = 1;
break;
}
}
if(!flag) //S[i]中的元素不在T中
{
for(k=1; k<=R[0]; k++)
{
if(S[i]==R[k])
{
flag = 1;
break;
}
}
}
if(!flag) //S[i]不在R中
{
R[0]++;
a[0]++;
R[R[0]] = S[i];
a[a[0]] = i;
}
}
}

View File

@@ -0,0 +1,85 @@
#include <stdio.h>
#include "../../../▲课本算法实现/▲04 串/01 SequenceString/SequenceString.c"//**▲04 串**//
/* 函数原型 */
void Algo_4_20(SString S, SString T);
int main(int argc, char *argv[])
{
char *s = "----***--*-**-****-*****-----";
char *t = "**";
SString T, S;
printf("删除前...\n");
StrAssign_Sq(S, s);
StrAssign_Sq(T, t);
printf("S = ");
StrPrint_Sq(S);
printf("\n");
printf("T = ");
StrPrint_Sq(T);
printf("\n\n");
printf("删除后...\n");
printf("S = ");
Algo_4_20(S, T);
StrPrint_Sq(S);
printf("\n\n");
return 0;
}
/*━━━━━━━━━━━┓
┃题4.20删除S中包含的T┃
┗━━━━━━━━━━━*/
void Algo_4_20(SString S, SString T)
{
int i, j, k;
i = 1;
j = 1;
while(i<=S[0] && j<=T[0]) //寻找第一个匹配的位置
{
if(S[i]==T[j])
{
i++;
j++;
}
else
{
i = i - (j-1) +1; //j-1代表徒劳地前进了j-1个位置
j = 1;
}
}
if(j>T[0] && T[0]) //T不为空串
i = i-T[0]; //匹配成功
else
i = 0;
while(i!=0) //有匹配的字符串
{
for(k=i+T[0]; k<=S[0]; k++)
S[k-T[0]] = S[k];
S[0] = S[0] - T[0]; //改变S长度
j = 1;
while(i<=S[0] && j<=T[0]) //定位下一个匹配的字符串
{
if(S[i]==T[j])
{
i++;
j++;
}
else
{
i = i - (j-1) +1; //j-1代表徒劳地前进了j-1个位置
j = 1;
}
}
if(j>T[0] && T[0]!=0) //T不为空串
i = i-T[0]; //匹配成功
else
i = 0;
}
}

View File

@@ -0,0 +1,233 @@
#include <stdio.h>
#include <string.h>
#include "../../../▲课本算法实现/▲01 绪论/Status.h" //**▲01 绪论**//
#include "../../../▲课本算法实现/▲02 线性表/04 SinglyLinkedList/SinglyLinkedList.c" //**▲02 线性表**//
/* 类型定义 */
typedef LElemType_L strElem;
typedef LNode strNode;
typedef LinkList String;
/* 函数原型 */
Status StrAssign_4_21(String *S, char *chars);
Status StrCopy_4_21(String *S, String T);
int StrCompare_4_21(String S, String T);
int StrLength_4_21(String S);
Status Concat_4_21(String *R, String S, String T);
Status SubString_4_21(String *Sub, String S, int pos, int len);
void StrPrint_4_21(String S);
int main(int argc, char *argv[])
{
char *chars = "@@***#*%%%****(((((*****)))";
String S, T, R, Sub;
int i;
StrAssign_4_21(&T, chars);
printf("T = ");
StrPrint_4_21(T);
printf("\n\n");
StrCopy_4_21(&S, T);
printf("S = ");
StrPrint_4_21(S);
printf("\n\n");
i = StrCompare_4_21(S, T);
if(i>0)
printf("S > T\n");
else if (i<0)
printf("S < T\n");
else
printf("S = T\n");
printf("\n");
i = StrLength_4_21(S);
printf("S_len = %d\n", i);
printf("\n");
Concat_4_21(&R, S, T);
printf("R = ");
StrPrint_4_21(R);
printf("\n\n");
SubString_4_21(&Sub, S, 11, 4);
printf("Sub = ");
StrPrint_4_21(Sub);
printf("\n\n");
return 0;
}
/*━━━━━━━━━┓
┃题4.21:字符串赋值┃
┗━━━━━━━━━*/
/* (1) */
Status StrAssign_4_21(String *S, char *chars)
{
int i, len;
String s, p;
len = strlen(chars);
InitList_L(S);
for(i=1,p=*S; i<=len; i++)
{
s = (String)malloc(sizeof(strNode));
if(!s)
exit(OVERFLOW);
s->data = chars[i-1];
s->next = p->next;
p->next = s;
p = p->next;
}
return OK;
}
/*━━━━━━━━━┓
┃题4.21:字符串复制┃
┗━━━━━━━━━*/
/* (2) */
Status StrCopy_4_21(String *S, String T)
{
String r, p, s;
if(!T)
return ERROR;
InitList_L(S);
for(r=*S,p=T->next; p; p=p->next)
{
s = (String)malloc(sizeof(strNode));
if(!s)
exit(OVERFLOW);
s->data = p->data;
s->next = r->next;
r->next = s;
r = r->next;
}
return OK;
}
/*━━━━━━━━━┓
┃题4.21:字符串比较┃
┗━━━━━━━━━*/
/* (3) */
int StrCompare_4_21(String S, String T)
{
String p, q;
if(S && T)
{
p = S->next;
q = T->next;
while(p && q)
{
if(p->data!=q->data)
return p->data - q->data;
p = p->next;
q = q->next;
}
return ListLength_L(S)-ListLength_L(T);
}
}
/*━━━━━━━━━┓
┃题4.21:字符串求长┃
┗━━━━━━━━━*/
/* (4) */
int StrLength_4_21(String S)
{
return ListLength_L(S);
}
/*━━━━━━━━━┓
┃题4.21:字符串拼接┃
┗━━━━━━━━━*/
/* (5) */
Status Concat_4_21(String *R, String S, String T)
{
String r, p, s;
if(!S || !T)
return ERROR;
InitList_L(R);
for(r=*R,p=S->next; p; p=p->next)
{
s = (String)malloc(sizeof(strNode));
if(!s)
exit(OVERFLOW);
s->data = p->data;
s->next = r->next;
r->next = s;
r = r->next;
}
for(p=T->next; p; p=p->next)
{
s = (String)malloc(sizeof(strNode));
if(!s)
exit(OVERFLOW);
s->data = p->data;
s->next = r->next;
r->next = s;
r = r->next;
}
}
/*━━━━━━━━━┓
┃题4.21:字符串提取┃
┗━━━━━━━━━*/
/* (6) */
Status SubString_4_21(String *Sub, String S, int pos, int len)
{
int i, sl;
String r, p, s;
sl = StrLength_4_21(S);
if(!S || pos<1 || pos>sl || len<0 || pos+len-1>sl)
return ERROR;
InitList_L(Sub);
for(i=1,p=S->next; i<pos; i++,p=p->next)
; //寻找第pos个结点
for(i=1,r=*Sub; i<=len; i++,p=p->next)
{
s = (String)malloc(sizeof(strNode));
if(!s)
exit(OVERFLOW);
s->data = p->data;
s->next = r->next;
r->next = s;
r = r->next;
}
return OK;
}
/* 字符串输出 */
void StrPrint_4_21(String S)
{
String p;
for(p=S->next; p; p=p->next)
printf("%c", p->data);
}

View File

@@ -0,0 +1,50 @@
#include <stdio.h>
#include "../../../▲课本算法实现/▲04 串/03 BlockChainString/BlockChainString.c"//**▲04 串**//
/* 函数原型 */
void Algo_4_22(LString S, LString *T, char ch);
int main(int argc, char *argv[])
{
char *t = "----***--*-**-**^**-*****-----";
char *s = "12345";
char ch = '^';
LString T, S;
StrAssign_L(&T, t);
StrAssign_L(&S, s);
printf("T = ");
StrPrint_L(T);
printf("\n");
printf("S = ");
StrPrint_L(S);
printf("\n\n");
Algo_4_22(S, &T, ch);
printf("T = ");
StrPrint_L(T);
printf("\n\n");
return 0;
}
/*━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓
┃题4.22将S插入到T的某个字符之后若不存在则插在T的末位 ┃
┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━*/
void Algo_4_22(LString S, LString *T, char ch)
{
int i;
char tmp[2];
LString Tmp;
tmp[0] = ch;
tmp[1] = '\0';
StrAssign_L(&Tmp, tmp);
i = Index_L((*T), Tmp, 1); //寻找字符ch在T中的位置
if(i)
StrInsert_L(T, i+1, S); //S插入在T的第i+1个字符前
else
StrInsert_L(T, (*T).curlen+1, S); //S插入在T的最后
}

View File

@@ -0,0 +1,70 @@
#include <stdio.h>
#include "../../../▲课本算法实现/▲03 栈和队列/01 SequenceStack/SequenceStack.c"//**▲03 栈和队列**//
#include "../../../▲课本算法实现/▲04 串/03 BlockChainString/BlockChainString.c"//**▲04 串**//
/* 函数原型 */
Status Algo_4_23(LString T);
int main(int argc, char *argv[])
{
char *t = "abcdefgfedcba";
LString T;
StrAssign_L(&T, t);
printf("T = ");
StrPrint_L(T);
printf("\n\n");
Algo_4_23(T) ? printf("T是对称串") : printf("T是非对称串");
printf("\n\n");
return 0;
}
/*━━━━━━━━━━━┓
┃题4.23:判断串是否对称┃
┗━━━━━━━━━━━*/
/* 借助于栈的操作来实现此函数栈中数据元素定义为char */
Status Algo_4_23(LString T)
{
int i, j, m;
SqStack S;
SElemType_Sq e;
Chunk *p;
if(!(T.curlen))
return OK;
InitStack_Sq(&S);
m = T.curlen/2;
for(i=1,p=T.head,j=0; i<=m; i++)
{
Push_Sq(&S, p->ch[j]);
j = (j+1) % CHUNKSIZE;
if(!j)
p = p->next;
}
if(T.curlen % 2) //长度为奇数则跳过一个字符
{
i++;
j = (j+1) % CHUNKSIZE;
if(!j)
p = p->next;
}
while(!StackEmpty_Sq(S) && i<=T.curlen)
{
Pop_Sq(&S, &e);
if(e!=p->ch[j])
return ERROR;
i++;
j = (j+1) % CHUNKSIZE;
if(!j)
p = p->next;
}
if(StackEmpty_Sq(S) && i>T.curlen)
return OK;
}

View File

@@ -0,0 +1,91 @@
#include <stdio.h>
#include "../../../▲课本算法实现/▲01 绪论/Status.h" //**▲01 绪论**//
#include "../../../▲课本算法实现/▲04 串/02 HeapString/HeapString.c"//**▲04 串**//
/* 函数原型 */
Status Concat_4_24(HString *T, HString S1, HString S2);
Status Replace_4_25(HString *S, HString T, HString V);
Status StrInsert_4_26(HString *S, int pos, HString T);
int main(int argc, char *argv[])
{
char *s = "---*^***^*^*^*---";
char *s1 = "*";
char *s2 = "^*";
char *v = "*_*";
HString S1, S2, T, V, S;
StrAssign_H(&S1, s1);
StrAssign_H(&S2, s2);
StrAssign_H(&V, v);
StrAssign_H(&S, s);
printf("S1 = ");
StrPrint_H(S1);
printf("\n");
printf("S2 = ");
StrPrint_H(S2);
printf("\n");
printf("V = ");
StrPrint_H(V);
printf("\n");
printf("S = ");
StrPrint_H(S);
printf("\n\n");
printf("███题 4.24 验证...███\n");
printf("连接S1和S2为T...\n");
Concat_4_24(&T, S1, S2);
printf("T = ");
StrPrint_H(T);
printf("\n\n");
printf("███题 4.25 验证...███\n");
printf("用 V 替换 S 中的 T...\n");
Replace_4_25(&S, T, V);
printf("S = ");
StrPrint_H(S);
printf("\n\n");
printf("███题 4.26 验证...███\n");
printf("将 T 插入到 S 的第 2 个字符前...\n");
StrInsert_4_26(&S, 2, T);
printf("S = ");
StrPrint_H(S);
printf("\n\n");
return 0;
}
/*━━━━━━━┓
┃题4.24:串连接┃
┗━━━━━━━*/
Status Concat_4_24(HString *T, HString S1, HString S2)
{
if(Concat_H(T, S1, S2)) //已定义
return OK;
else
return ERROR;
}
/*━━━━━━━┓
┃题4.25:串替换┃
┗━━━━━━━*/
Status Replace_4_25(HString *S, HString T, HString V)
{
if(Replace_H(S, T, V)) //已定义
return OK;
else
return ERROR;
}
/*━━━━━━━┓
┃题4.26:串插入┃
┗━━━━━━━*/
Status StrInsert_4_26(HString *S, int pos, HString T)
{
if(StrInsert_H(S, pos, T)) //已定义
return OK;
else
return ERROR;
}

View File

@@ -0,0 +1,60 @@
#include <stdio.h>
#include "../../../▲课本算法实现/▲01 绪论/Status.h" //**▲01 绪论**//
#include "../../../▲课本算法实现/▲04 串/01 SequenceString/SequenceString.c" //**▲04 串**//
/* 函数原型 */
int Algo_4_27(SString S, SString T, int pos);
int main(int argc, char *argv[])
{
char *s = "aaaaaaaaaaaaaaab";
char *t = "aaaab";
SString S, T;
StrAssign_Sq(S, s);
StrAssign_Sq(T, t);
printf("S = ");
StrPrint_Sq(S);
printf("\n");
printf("T = ");
StrPrint_Sq(T);
printf("\n\n");
printf("T在S中首次出现的位置为");
printf("%d\n", Algo_4_27(S, T, 1));
printf("\n");
return 0;
}
/*━━━━━━━━┓
┃题4.27:子串定位┃
┗━━━━━━━━*/
int Algo_4_27(SString S, SString T, int pos)
{
int i = pos;
int j = 1;
if(pos<1)
return 0;
while(i<=S[0] && j<=T[0])
{
if((j!=1&&S[i]==T[j])||(j==1&&S[i]==T[j]&&S[i+T[0]-1]==T[T[0]]))
{
i++;
j++;
}
else
{
i = i - (j-1) +1;
j = 1;
}
}
if(j>T[0] && T[0]) //T不为空串
return i-T[0]; //匹配成功
else
return 0;
}

View File

@@ -0,0 +1,204 @@
#include <stdio.h>
#include <stdlib.h>
#include "../../../▲课本算法实现/▲01 绪论/Status.h" //**▲01 绪论**//
/* 串结构类型定义 */
typedef struct strLNode //主串是个双向链表不循环模式串在未求next值之前与主串类似
{
char chdata;
struct strLNode *succ; //succ指向后继
struct strLNode *next; //next在主串中指向前驱
}strLNode; //next在模式串中指向当前结点失配时下一个应该比较的结点
typedef strLNode *LString;
/* 函数原型 */
Status Algo_4_28_1(LString T);
Status Algo_4_28_2(LString T) ;
int Algo_4_29(LString S, LString T, int pos);
Status AssignLString(LString *S, char *s);
Status PrintLString(LString S);
int main(int argc, char *argv[])
{
int pos, i1, i2;
LString S, T1, T2;
char *s = "abaaabaababaabcaabaabcacabaabcaabaabcac";
char *t = "abaabcac";
LString p;
AssignLString(&S, s); //主串
AssignLString(&T1, t); //模式串
AssignLString(&T2, t);
printf("主 串 S = ");
PrintLString(S);
printf("\n");
printf("模式串 T1 = ");
PrintLString(T1);
printf("\n");
printf("模式串 T2 = ");
PrintLString(T2);
printf("\n\n");
printf("███题 4.28 验证...███\n");
Algo_4_28_1(T1);
Algo_4_28_2(T2);
printf("创建next表...\n");
printf("\n");
printf("███题 4.29 验证...███\n");
i1 = Algo_4_29(S, T1, 1);
printf("模式串 T1 从 %d 个字符起第一次匹配成功的位置为i1 = %d\n", 1, i1);
i2 = Algo_4_29(S, T2, 1);
printf("模式串 T2 从 %d 个字符起第一次匹配成功的位置为i2 = %d\n", 1, i2);
printf("\n");
return 0;
}
/*━━━━━━━━━┓
┃题4.28-1求next值┃
┗━━━━━━━━━*/
/* 方案1求next值 */
Status Algo_4_28_1(LString T)
{
strLNode *i, *j;
if(!T || !T->succ)
return ERROR;
i = T->succ; //i = 1
j = T; //j = 0
i->next = T; //第一个字符处失配
while(i->succ)
{
if(j==T || i->chdata==j->chdata)
{
i = i->succ;
j = j->succ;
i->next = j;
}
else
j = j->next;
}
return OK;
}
/*━━━━━━━━━┓
┃题4.28-2求next值┃
┗━━━━━━━━━*/
/* 方案2求nextval值即改进后的求next方案 */
Status Algo_4_28_2(LString T)
{
strLNode *i, *j;
if(!T || !T->succ)
return ERROR;
i = T->succ; //i = 1
j = T; //j = 0
i->next = T; //第一个字符处失配
while(i->succ)
{
if(j==T || i->chdata==j->chdata)
{
i = i->succ;
j = j->succ;
if(i->chdata!=j->chdata)
i->next = j;
else
i->next = j->next;
}
else
j = j->next;
}
return OK;
}
/*━━━━━━━━┓
┃题4.29KMP算法 ┃
┗━━━━━━━━*/
int Algo_4_29(LString S, LString T, int pos)
{
int count, m;
strLNode *i, *j; //i遍历Sj遍历T
strLNode *p, *q;
if(pos<1 || !S || !S->succ || !T || !T->succ)
return 0;
for(count=1,i=S->succ; count<pos; count++,i=i->succ)
; //用i指向第pos个结点
j = T->succ;
p = i;
while(i && j)
{
if(j==T || i->chdata==j->chdata)
{
i = i->succ;
j = j->succ;
}
else
{
j = j->next;
if(j==T->succ)
p = i; //记下重新开始匹配时i的起点
}
}
if(!j)
{
for(count=1,q=S->succ; q!=p; count++,q=q->succ)
; //找出第一个结点匹配的位置
return count;
}
else
return 0;
}
Status AssignLString(LString *S, char *s)
{
int i;
LString pre, p;
*S = (LString)malloc(sizeof(strLNode));
if(!(*S))
exit(OVERFLOW);
(*S)->next = (*S)->succ = NULL;
for(i=0,pre=*S; i<strlen(s); i++)
{
p = (LString)malloc(sizeof(strLNode));
if(!p)
exit(OVERFLOW);
p->chdata = s[i];
p->next = pre;
p->succ = pre->succ;
pre->succ = p;
pre = pre->succ;
}
return OK;
}
Status PrintLString(LString S)
{
LString p;
if(!S)
return ERROR;
for(p=S->succ; p; p=p->succ)
printf("%c", p->chdata);
return OK;
}

View File

@@ -0,0 +1,80 @@
#include <stdio.h>
#include "../../../▲课本算法实现/▲04 串/01 SequenceString/SequenceString.c"//**▲04 串**//
/* 函数原型 */
Status Algo_4_30(SString S, SString Sub, int *pos);
int main(int argc, char *argv[])
{
char *s = "abcdeabcabcbcdefbcdefefghefgh";
SString Sub, S;
int pos;
StrAssign_Sq(S, s);
printf("主串...\n");
printf("S = ");
StrPrint_Sq(S);
printf("\n\n");
printf("首个最长不重复子串...\n");
printf("Sub = ");
Algo_4_30(S, Sub, &pos);
StrPrint_Sq(Sub);
printf("\n");
printf("Sub 在 S中首次出现的位置为 %d\n", pos);
printf("\n");
return 0;
}
/*━━━━━━━━━━━━━━━━━━━━┓
┃题4.30:求首次出现的最长重复子串及其位置┃
┗━━━━━━━━━━━━━━━━━━━━*/
/*
**此处的最长重复子串有三层含义:
**第一:此子串在所有重复子串中是首个出现且最长的;
**第二子串间可以重叠比如求取abcabca的结果为abca
**第三子串内可以重复如求取aaaa的结果为aaa。
*/
Status Algo_4_30(SString S, SString Sub, int *pos) //0号单元
{
int i, j, k, len, start, end;
if(S[0]<2) //主串元素个数不能少于2
return ERROR;
Sub[0] = 0;
for(k=1; k<S[0]; k++) //范围从1到S[0]-1
{
i = k;
j = k+1;
while(j<=S[0] && S[i]!=S[j])
j++; //找到首个潜在的循环起点
if(j<=S[0])
{
start = i;
end = j;
len = 0;
while(j<=S[0] && S[i]==S[j])
{
i++;
j++;
len++;
}
if(len>Sub[0] && start+len-1>=end-1 ) //保证连续性和最长这两个特性
{
*pos = start;
SubString_Sq(Sub, S, start, len);
}
}
}
if(Sub[0])
return OK;
else
return ERROR;
}

View File

@@ -0,0 +1,162 @@
#include <stdio.h>
#include "../../../▲课本算法实现/▲01 绪论/Status.h" //**▲01 绪论**//
#include "../../../▲课本算法实现/▲04 串/01 SequenceString/SequenceString.c"//**▲04 串**//
/* 宏定义 */
#define Sl 2000
/* 类型定义 */
typedef struct
{
SString String; //某个最长的公共
int start; //字符串起点
}PString;
typedef struct
{
PString Sub[MAXSTRLEN+1];
int count;
}StringSet; //满足条件的子串集合
/* 函数原型 */
Status Algo_4_31(SString S, SString T, StringSet *Set_s, StringSet *Set_t);
Status StringSetPrint(StringSet Set);
int main(int argc, char *argv[])
{
char *s = "abcd*lokis***hyuij**vfgh*lokis****yu*mklng***u****wy*c*vdgry*pklnh";
char *t = "-vdgry--vfgh-hyuij---abcd-pklnh---yu----lokis-----uio-u--wy---mklng-c ";
SString S, T;
StringSet Set_s, Set_t;
printf("初始化...\n");
StrAssign_Sq(S, s);
StrAssign_Sq(T, t);
printf("S = ");
StrPrint_Sq(S);
printf("\n");
printf("T = ");
StrPrint_Sq(T);
printf("\n\n");
printf("求取公共子串的集合...\n");
Algo_4_31(S, T, &Set_s, &Set_t);
printf("\n");
printf("输出 S 中公共子串信息...\n");
StringSetPrint(Set_s);
printf("\n");
printf("输出 T 中公共子串信息...\n");
StringSetPrint(Set_t);
printf("\n");
return 0;
}
/*━━━━━━━━━━┓
┃题4.31:最长公共子串┃
┗━━━━━━━━━━*/
/* 结构StringSet保存串S和串T所有的最长公共子串及其起始位置和数量 */
Status Algo_4_31(SString S, SString T, StringSet *Set_s, StringSet *Set_t)
{
int i, j; //i标记Sj标记T
int m, n;
int k, flag;
int len[MAXSTRLEN+1][MAXSTRLEN+1];
if(!S[0] || !T[0]) //有字符串为空
return ERROR;
for(m=0; m<=T[0]; m++) //初始化首列为0
len[m][0] = 0;
for(n=0; n<=S[0]; n++) //初始化首行为0
len[0][n] = 0;
m = T[0]+1;
n = 1;
while(n<=S[0])
{
m>1 ? m-- : n++;
for(i=m,j=n; i<=T[0]&&j<=S[0]; i++,j++)
{
if(T[i]==S[j])
len[i][j] = len[i-1][j-1] + 1;
else
len[i][j] = 0;
if(len[i][j]>len[m-1][n-1])
len[m-1][n-1] = len[i][j];
if(len[i][j]>len[0][S[0]])
len[T[0]][0] = len[0][S[0]] = len[i][j];
}
}
if(!len[0][S[0]])//两字符串无最长公共子串
return ERROR;
m = T[0]+1;
n = 1;
(*Set_s).count = (*Set_t).count = 0;
while(n<=S[0])
{
m>1 ? m-- : n++;
if(len[m-1][n-1]==len[0][S[0]])//存在最长公共子串
{
for(i=m,j=n; i+len[0][S[0]]-1<=T[0]&&j+len[0][S[0]]-1<=S[0]; i++,j++)
{
if(len[i+len[0][S[0]]-1][j+len[0][S[0]]-1]==len[0][S[0]])//满足条件的字符串起点
{
for(k=1,flag=0; k<=(*Set_t).count; k++)//是否已加入T中
{
if((*Set_t).Sub[k].start==i)
{
flag = 1;
break;
}
}
if(!flag)//收集T中出现的最长公共字符串
{
(*Set_t).count++;
(*Set_t).Sub[(*Set_t).count].start = i;
SubString_Sq((*Set_t).Sub[(*Set_t).count].String, T, i, len[T[0]][0]);
}
for(k=1,flag=0; k<=(*Set_s).count; k++)//是否已加入S中
{
if((*Set_s).Sub[k].start==j)
{
flag = 1;
break;
}
}
if(!flag)//收集S中出现的最长公共字符串
{
(*Set_s).count++;
(*Set_s).Sub[(*Set_s).count].start = j;
SubString_Sq((*Set_s).Sub[(*Set_s).count].String, S, j, len[0][S[0]]);
}
}
}
}
}
return OK;
}
Status StringSetPrint(StringSet Set)
{
int i, j, k;
for(k=1; k<=Set.count; k++)
{
printf("第 %2d 个位置:", Set.Sub[k].start);
StrPrint_Sq(Set.Sub[k].String);
printf("\n");
}
}

View File

@@ -0,0 +1,192 @@
# 第4章 串
## 一、基础知识题
### 4.1 简述空串和空格串(或称空格符串)的区别。
> 一个空字符为:‘\0 ,一个空格字符为:‘ 。空串是只包含一个空字符的字符串其长度为0。
> 空格串是除了在结尾包含空字符外,还包含若干空格字符的字符串,统计其长度时,要将除空字符外的字符个数都计算在内。
### 4.2 对于教科书4.1节中所述串的各个基本操作,讨论是否可由其他基本操作构造而得,如何构造?
> 对于串操作中的最小操作子集即串赋值StrAssign、串比较StrCompare、求串长StrLength、串联接Conact以及求子串SubString5种操作不可由其他操作来实现。
> 其他串操作则可利用串的最小操作子集实现。
### 4.3 设s = I AM A STUDENTt = GOODq = WORKER
##### 求StrLength(s)StrLength(t)SubString(s, 8, 7)SubString(t, 2, 1)Index(s, A)Index(s, t)Replace(s, STUDENT, q)Concat(SubString(s, 6, 2), Concat(t, SubString(s, 7, 8)))。
> StrLength(s) = 14;
> StrLength(t) = 4;
> SubString(s, 8, 7) = STUDENT;
> SubString(t, 2, 1) = O;
> Index(s, A) = 3;
> Index(s, t) = 0;
> Replace(s, STUDENT, q) = I AM A WORKER;
> Concat(SubString(s, 6, 2), Concat(t, SubString(s, 7, 8))) = A GOOD STDENT.
### 4.4 已知下列字符串
##### a = THIS, f = A SAMPLE, c = GOOD, d = NE, b = .
##### s = Concat(a, Concat(SubString(f, 2, 7), Concat(b, SubString(a, 3, 2)))),
##### t = Replace(f, SubString(f, 3, 6), c),
##### u = Concat(SubString(c, 3, 1), d),
##### g = IS,
##### v = Concat(s, Concat(b, Concat(t, Concat(b, u)))),
##### 试问stvStrLength(s)Index(v, g)Index(u, g)各是什么?
> s = THIS SAMOLE IS;
> t = A GOOD;
> v = THIS SAMPLE IS A GOOD ONE;
> StrLength(s) = 14;
> Index(v, g) = 3;
> Index(u, g) = 0.
### 4.5 试问执行以下函数会产生怎样的输出结果?
```c
void demonstrate()
{
StrAssign(s, THIS IS A BOOK);
Replace(s, SubString(s, 3, 7), ESE ARE);
StrAssign(t, Concat(s, S));
StrAssign(u, XYXYXYXYXYXY);
StrAssign(v, SubString(u, 6, 3));
StrAssign(w, W);
printf(t=, t, v=, v, u=, Replace(u, v, w));
}//demonstrate
```
> t=THESE ARE BOOKS,v=YXY,u=XWXWXW.
### 4.6 已知s = (XYZ)+*,t = (X+Z)*Y。试利用联接、求子串和置换等基本运算将s转化为t。
> S1 = SubString(s, 3, 1); //S1 = Y
> S2 = SubString(s, 6, 1); //S2 = +
> Replace(s, S1, S2); //s = (X+Z)+*
> Concat(S3, s, S1); //S3 = (X+Z)+*Y
> Concat(t, SubString(S3, 1, 5), SubString(S3, 7, 2));
### 4.7 令s = aaab,t = abcabaa,u = abcaabbabcabaacbacba。试分别求出它们的next函数值和nextval函数值。
> **s**
![4.7.1](_v_images/20181128012650395_14443.png)
> **t**
![4.7.2](_v_images/20181128012749064_24270.png)
> **u**
![4.7.3](_v_images/20181128012817985_10766.png)
### 4.8 已知主串s = ADBADABBAABADABBADADA模式串pat = ADABBADADA写出模式串的nextval函数值并由此画出KMP算法匹配的全过程。
![4.8.1](_v_images/20181128013044407_30919.png)
![4.8.2](_v_images/20181128013157410_30749.png)
### 4.9 在以链表存储串值时存储密度是结点大小和串长的函数。假设每个字符占一个字节每个指针占4个字节每个结点的大小为4的整数倍已知串长的分布函数为f(l)且![4.9.1](_v_images/20181128013251526_202.png)求结点大小为4k串长为l时的存储密度d(4k, l)(用公式表示)。
![4.9.2](_v_images/20181128013312950_14120.png)
## 二、算法设计题
```c
4.104.14StringType数据类型
StringType是串的一个抽象数据类型
void StrAssign (StringType &t, StringType s)
//将s的值赋给t。s的实际参数可以是串变量或者串常量abcd
int StrCompare (StringType s, StringType t)
//比较s和t。若s>t返回值>0若s=t返回值=0若s<t返回值<0
int StrLength (StringType s)
//返回s中的元素个数即该串的长度
StringType Concat (StringType s, StringType t)
//返回由s和t联接而成的新串
StringType SubString (StringType s, int start, int len)
// 当1≤start≤StrLength(s)且0≤len≤StrLength(s)-start+1时
// 返回s中第start个字符起长度为len的子串否则返回空串
```
### 4.10 编写对串求逆的递推算法。
>[Question-4.10-main.c](▼习题测试文档-04/Question-4.10-main.c)
### 4.11 编写算法求得所有包含在串s中而不包含在串t中的字符s中重复的字符只选一个构成的新串r以及r中每个字符在s中第一次出现的位置。
>[Question-4.11-main.c](▼习题测试文档-04/Question-4.11-main.c)
### 4.12 编写一个实现串的置换操作Replace(&S, T, V)的算法。
>[Question-4.12-main.c](▼习题测试文档-04/Question-4.12-main.c)
### 4.13 编写算法从串s中删除所有和串t相同的子串。
>[Question-4.13-main.c](▼习题测试文档-04/Question-4.13-main.c)
### 4.14 利用串的基本操作以及栈和集合的基本操作,编写“由一个算术表达式的前缀式求后缀式”的递推算法(假设前缀式不含语法错误)。
>[Question-4.14-main.c](▼习题测试文档-04/Question-4.14-main.c)
>> ### 在编写4.15至4.20题的算法时请采用教科书4.2.1节中所定义的定长顺序存储表示,而不允许调用串的基本操作。
### 4.15 编写算法实现串的基本操作StrAssign(&T, chars)。
### 4.16 编写算法实现串的基本操作StrCompare(S, T)。
### 4.17 编写算法实现串的基本操作Replace(&S, T, V)。
>[Question-4.15~4.17-main.c](▼习题测试文档-04/Question-4.15~4.17-main.c)
### 4.18 编写算法求串s所含不同字符的总数和每种字符的个数。
>[Question-4.18-main .c](▼习题测试文档-04/Question-4.18-main%20.c)
### 4.19 在串的定长顺序存储结构上直接实现4.11题要求的算法。
>[Question-4.19-main .c](▼习题测试文档-04/Question-4.19-main%20.c)
### 4.20 编写算法从串s中删除所有和串t相同的子串。
>[Question-4.20-main .c](▼习题测试文档-04/Question-4.20-main%20.c)
### 4.21 假设以结点大小为1且附设头结点的链表结构表示串。试编写实现下列六种串的基本操作StrAssignStrCopyStrCompareStrLengthConcat和SubString的函数。
>[Question-4.21-main .c](▼习题测试文档-04/Question-4.21-main%20.c)
### 4.22 假设以块链结构表示串。试编写将串s插入到串t中某个字符之后的算法若串t中不存在此字符则将串s联接在串t的末尾
>[Question-4.22-main .c](▼习题测试文档-04/Question-4.22-main%20.c)
### 4.23 假设以块链结构作串的存储结构。试编写判别给定串是否具有对称性的算法并要求算法的时间复杂度为O(StrLength(S))。
>[Question-4.23-main .c](▼习题测试文档-04/Question-4.23-main%20.c)
>> ### 在编写4.24至4.26题的算法时请采用教科书4.2.2节中所定义的堆分配存储表示。
### 4.24 试写一算法在串的堆存储结构上实现串基本操作Concat(&T, s1s2)。
### 4.25 试写一算法实现堆存储结构的串的置换操作Replace(&S, T, V)。
### 4.26 试写一算法,实现堆存储结构的串的插入操作 StrInsert(&S, pos, T)。
>[Question-4.24~4.26-main .c](▼习题测试文档-04/Question-4.24~4.26-main%20.c)
### 4.27 当以教科书4.2.1节中定义的定长顺序结构表示串时可如下所述改进定位函数的算法先将模式串t中的第一个字符和最后一个字符与主串s中相应的字符比较在两次比较都相等之后再依次从t的第二个字符逐个比较。这样做可以克服算法Index算法4.5在求模式串a<sup>k</sup>ba<sup>k</sup>表示连续k个字符a 在主串a<sup>n</sup>bk≤n中的定位函数时产生的弊病。试编写上述改进算法并比较这两种算法在作Indexa<sup>n</sup>b,a<sup>k</sup>b运算时所需进行的字符间的比较次数。
>[Question-4.27-main .c](▼习题测试文档-04/Question-4.27-main%20.c)
### 4.28 假设以结点大小为1带头结点的链表结构表示串则在利用next函数值进行串匹配时在每个结点中需设三个域数据域chdata、指针域succ和指针域next。其中chdata域存放一个字符succ域存放指向同一链表中后继结点的指针next域在主串中存放指向同一链表中前驱结点的指针在模式串中存放指向当该结点的字符与主串中的字符不等时在模式串中下一个应进行比较的字符结点即与该字符的next函数值相对应的字符结点的指针若该节点字符的next函数值为0则其next域的值应指向头结点。试按上述定义的结构改写求模式串的next函数值的算法。
### 4.29 试按4.28题定义的结构改写串匹配的改进算法KMP算法
>[Question-4.28~4.29-main .c](▼习题测试文档-04/Question-4.28~4.29-main%20.c)
### 4.30 假设以定长顺序存储结构表示串试设计一个算法求串s中出现的第一个最长重复子串及其第一次出现的位置并分析你的算法的时间复杂度。
>[Question-4.30-main .c](▼习题测试文档-04/Question-4.30-main%20.c)
### 4.31 假设以定长顺序存储结构表示串试设计一个算法求串s和串t的一个最长公共子串并分析你的时间复杂度。若要求第一个出现的最长公共子串即它在串s和串t的最左边的位置上出现和所有的最长公共子串讨论你的算法能否实现。
>[Question-4.31-main .c](▼习题测试文档-04/Question-4.31-main%20.c)