如有问题,欢迎评论区指正,因为时间和精力问题,部分题只给出思路,后续有时间会逐步完善,写不完,根本写不完啊,不然更新太慢了
1.简述下列术语:
(1)空串和空格串。
空串是长度为零的串,空格串是所有元素为空格的串
(2)串变量和串常量。
串变量是程序中用于存储字符串的变量,随着程序的运行,变量值可以改变
串常量是一个固定的字符串值
(3)主串和子串。
主串:包含子串的串称为主串
子串:主串中任意连续的子序列
(4)串变量的名字和串变量的值。
串变量的名字即变量名,串变量的值即变量存储的串值
2.选择题:
(1)函数 substr (" DATASTRUCTURE ",5,9)的返回值为(A).
A ." STRUCTURE "
B ." DATA "
C ." ASTRUCTUR "
D ." DATASTRUCTURE "
substr (str,pos,len)返回串str中pos位置其长度为len的子串
(2)下面关于串的叙述中,不正确的是(B)。
A .串是字符的有限序列
B .空串是由空格构成的串
C .模式匹配是串的一种重要运算
D .串既可以采用顺序存储,也可以采用链式存储
(3) StrCompare (' Computer ',' Compare ')的返回值是()。
A .-1
B .0
C .1
D .100
StrCompare(str1,str2);
依据字典序比较str1与str2
- str1 = str2 返回0
- 第一个不相等的字符 str1.i > str2.i 则返回1
- 第一个不相等的字符 str1.i < str2.i 则返回1
3.编写算法,实现顺序串的基本操作 StrReplace ( S , T , V )。
StrReplace(S,T,V);
串 S,T,V存在,使用V替换S中所有不重叠的T子串
答:
在顺序串的求子串、替换的基础上操作S串即可
4.假设以单链表结构表示串,每个结点数据域存放一个字符,且附设头结点。试编写算法,实现串的下列操作:
- StrAssign ( S , chars ); //生成一个值为chars的串
- StrCopy ( S , T ); //将串T复制到S
- StrCompare ( S , T );//比较串 S和T
- StrLength ( S );//返回串S的长度
- StrCat ( S , T );//将串T连接到S的后面
- SubString ( Sub , S , pos , len )。//返回pos位置起长度为len的子串
#include <stdio.h>
//定义链式存储的串节点
typedef struct SNode{
char data;
struct SNode *next;
}LinkString;
void StrAssign(LinkString *S, char chars[],int n){
//初始化头结点
S = (LinkString *)malloc(sizeof(struct SNode));
S->next = NULL:
struct Snode * t = S;
struct SNode * p;
for(int i=0;i<n;i++){
p = (LinkString *)malloc(sizeof(struct SNode));
p->data = chars[i];
p->next = t->next;
t->next = p;
t = p;
}
}
void StrCopy(LinkString *S, LinkString *T){
/*
需要考虑原先S和T长度问题
S的长度大于T ,则逐个复制之后需要释放S多余的结点
S的长度小于T , 则逐个复制之后还需要新建结点
S的长度等于T ,则逐个复制即可
*/
struct SNode *p = S;
struct SNode *t = T;
while(p->next && t->next){
p->next->data = t->next->data;
p = p->next;
t = t->next;
}
while(p->next!=NULL){
struct SNode *temp = p->next;
p->next = temp->next;
free(temp);
}
while(t->next!=NULL){
struct SNode *temp = (LinkString*)malloc(sizeof(struct SNode));
temp->data = t->next->data;
temp->next = p->next;
p->next = temp;
t = t->next;
}
}
int StrCompare(LinkString *S,LinkString *T){
struct SNode *p1 = S->next;
struct SNode *p2 = T->next;
while(p1 && p2){
if(p1->data == p2->data){
p1 = p1->next;
p2 = p2->next;
}else if(p1->data > p2->data){
return 1;
}else {
return -1;
}
}
if(p1){
return 1;
}
if(p2){
return -1;
}
return 0;
}
int StrLength(LinkString *S){
struct SNode *p = S->next;
int ret = 0;
while(p){
ret++;
p = p->next;
}
return ret;
}
void StrCat(LinkString *S,LinkString *T){
//将T附加到S的后面
struct SNode *p = S->next;
struct SNode *t = T->next;
while(p->next){
p = p->next;
}
while(t){
struct SNode *temp = (LinkString *)malloc(sizeof(struct SNode));
temp->data = t->data;
temp->next = p->next;
p->next = temp;
t = t->next;
}
}
LinkString *SubString(LinkString *S,int pos,int len){
LinkString * ret = (LinkString *)malloc(sizeof(struct SNode));
ret->next = NULL;
struct SNode *p = ret;
struct SNode *t = S->next;
while(pos--){
t = t->next;
}
while(len--){
struct SNode *temp = (LinkString *)malloc(sizeof(struct SNode));
temp->data = t->data;
temp->next = p->next;
p->next = temp;
p = temp;
t = t->next;
}
return ret;
}
5.已知: S =( xyz )*, T =( x + z )* y 。试利用连接、求子串和置换等操作,将 S 转换为 T 。
答:将S中的y替换为+,并在S后面连接y即可转换为T
6. S 和 T 是用结点大小为1的单链表存储的两个串,设计一个算法,将串 S 中首次与 T 匹配的子串逆置。
答:
首先找到串S中首次与T匹配的子串的位置
其次遍历链表并逆置链表
需要三个指针 prev(上个结点的指针) current(当前结点指针) next(下一个结点的指针)
记录并暂存起始指针位置
next = current->next
current->nexxxt = prev
prev = current
current = next
即将current结点的next指针指向前面结点,同时记录原来顺序的next和prev
7.S 是用结点大小为4的单链表存储的串,分别编写算法,实现在第 k 个字符后插入串 T ,并从第 k 个字符删除 len 个字符。
答:
遍历链表串 找到第k个字符所在的结点indexk
两种思路
- 当前结点记录有一个指示结点有效字符的变量,因此只需要将串T插入到indexk后面,改变indexk结点的有效字符数,将多余字符复制到结尾
- 不牺牲indexk结点的空间,将T中字符一个个添加到第k个字符的后面,并将原来第k个字符后面的字符后移。此时需要暂存当前结点,将串T链接到后面后再逐个排序
8.编写算法,实现定长顺序串的如下操作:
1)将串 r 中所有值为ch1的字符换成ch2。
2)将串r中所有字符按照相反的次序仍存放在r中。
3)从串 r 中删除其值等于 ch 的所有字符。
4)从串r1中第 index 个字符起,求出首次与串r2相同的子串的起始位置。
5)从串 r 中删除所有与串r1相同的子串。
答:
(1)遍历字符串替换即可
(2)对于定长顺序串,逆置串只需要从首尾向中间交换字符值即可
(3)使用双指针,一个指针用于遍历,一个指针用于指示删除字符后后面的字符应该迁移的位置
(4)使用Brute-Force算法或者KMP算法均可
(5)在第四步的基础上将后面串前移即可
9.编写一个函数,将顺序串s1中的第 i 个字符到第 j 个字符之间的字符用串s2替换。
答:要考虑的长度和S2的长度大小
如果长度相等 则直接逐个替换即可
如果前者大于后者 则逐个替换之后还需要将后面的字符前移
如果后者大于前者 则在替换之前需要将后面的字符后移
10.编写算法,实现顺序串的基本操作 StrCompare ( s , t )。
答:假设顺序串的定义如下
#define MaxSize 1000 typedef struct SString{ char data[1000]; int length; }SString;
void StrCompare(SString *S, SString *T){
int i = 0;
int j = 0;
while(i < S->length && j < T->length){
if(S->data[i] == T->data[j]){
i++;
j++;
}else if(s->data[i] > s->data [j]){
return 1;
}else {
return -1;
}
}
if( i < S->length){
return 1;
}
if(j < S->length){
return -1;
}
return 0;
}
11.编写算法,实现顺序串的基本操作 StrReplace (& s , t , v )。
答:思路同前面顺序串的子串替换
12.令主串 S =' aaabbbababaabb ',子串='abaa',试分别用 Brute - Force 算法和 KMP 算法给出其匹配过程,并讨论模式匹配的匹配效率。
答:
Brute-Force算法
每次不匹配时,指向S的指针回溯至上次起始位置的下一个位置,指向子串的指针返回开始,因此,使用Brute-Force算法时,在第九次匹配时才会匹配成功
KMP算法
设i指向主串S的下标 j指向子串T的下标 下标从0开始
首先计算子串“abaa”的next数组 【0,0,0,1】,此时从下标0开始,很多地方下标是从1开始的,若从1开始,则next数组为【0,1,1,2】
第一次 S[0:4] = ‘aaab’ 第二个字符匹配不成功 则进入第二次匹配 此时i = 1 j =0
第二次 S[1:5] = ‘aabb’ 第二个字符匹配不成功 则进入第三次匹配 此时i = 2 j =0
第三次 S[2,6] = 'abbb' 第三个字符匹配不成功 则进入第四次匹配 此时i = 4 j =0
第四次 S[4,9] = 'bbab' 第一个字符匹配不成功 则进入第四次匹配 此时i = 5 j =0
第五次 S[5,10] = 'baba' 第一个字符匹配不成功 则进入第四次匹配 此时i = 6 j =0
第六次 S[6,11] = 'abab' 第四个字符匹配不成功 则进入第四次匹配 此时i = 8 j =1
第七次 S[8,13] = 'abaa' 匹配成功
13.假设以顺序存储结构表示串,试设计一个算法,求串 S 和串 T 的一个最长公共子串,并分析算法的时间复杂度。
答:使用动态规划的思想解决问题
1.创建一个二位数组dp, 其中dp[i][j]表示以S[i] 和T[j]结尾的最长公共子串的长度
2.初始化dp[i][j], 如果S[i] = T[j] 则dp[i][j] = 1 否则等于0
3.遍历串S和T,进行状态转移如果s[i] = T[j], 则dp[i][j] = dp[i-1][j-1] +1 否则为0
4.状态转移过程中记录最大值以及i,j值
#include <stdio.h>
#define MaxSize 100
typedef struct SString{
int length;
char data[MaxSize];
}SString;
void getMax(SString *S,SString *T){
int dp[S->length][T->length];
int max = 0;
int indexi;
int indexj;
//初始化
for(int i = 0;i<S->length;i++ ){
for(int j = 0;j<T->length;j++){
if(S->data[i] == T->data[j]){
dp[i][j] = 1;
}else{
dp[i][j] = 0;
}
}
}
for(int i=0;i<S->length;i++){
for(int j=0;j<T->length;j++){
printf("%d\t",dp[i][j]);
}
printf("\n");
}
max = dp[0][0];
indexi = 0;
indexj = 0;
//状态转移
for(int i = 1;i<S->length;i++){
for(int j = 1;j<T->length;j++){
if(S->data[i] == T->data[j]){
dp[i][j] = dp[i-1][j-1] +1;
}else{
dp[i][j] = 0;
}
if(max<dp[i][j]){
max = dp[i][j];
indexi = i;
indexj = j;
}
}
}
for(int i=0;i<S->length;i++){
for(int j=0;j<T->length;j++){
printf("%d\t",dp[i][j]);
}
printf("\n");
}
printf("max = %d , indexi = %d , indexj = %d",max,indexi,indexj);
}
int main(){
SString S;
SString T;
char a[10] = "aabababbab";
char b[5] = "ababc";
S.length = 10;
T.length = 5;
for(int i=0;i<10;i++){
S.data[i] = a[i];
}
for(int i=0;i<5;i++){
T.data[i] = b[i];
}
getMax(&S,&T);
}