数据结构——串

头文件SString.h

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
// SString.h - 串
#include <iostream>

#define MAXLEN 255

/*********************************************************************************************************************************
* 数据类型一览
* SString 定长顺序存储(静态数组)
* HString 串的顺序存储 可拓展长度顺序存储(指针数组)
* StringNode, *Node 串的链式存储
*
* 操作函数 共享栈操作在函数名后加0或者1 不带头结点的链栈操作在函数名后加WithoutFirstNode
* bool StrAssign(&T, *ch) 赋值操作,将字符串ch复制到串T中 正常结束返回1,否则返回0
* bool StrCopy(&T, S) 复制操作,将S串复制到串T中 正常结束返回1,否则返回0
* bool StrEmpty(S) 判空 空返回1,否则返回0
* int StrLength(S) 求长度 返回串的长度
* bool ClearString(S) 清空 正常结束返回1,否则返回0
* bool DestroyString(&S) 销毁 正常结束返回1,否则返回0
* bool Concat(&T, S1, S2) 串连接,将S1和S2连接后存入T 正常结束返回1,否则返回0
* bool SubString(&Sub, S, pos, len) 求子串,求出串S中位于pos位置的长度为len长度的子串存入Sub 正常结束返回1,否则返回0
* int StrCompare(S, T) 比较操作 比较串S和T的大小,返回值小于0,等于0,大于0,分别表示S<T,S=T,S>T
* int Index(S, T) 定位操作,求出串S中第一次出现串T的位置 返回值为定位串T的位置,如果没有找到返回0
* int Index2(S, T) 朴素模式匹配,求出串S中第一次出现串T的位置 返回值为定位串T的位置,如果没有找到返回0
* void get_next(T, next) 求模式串T的next数组
* void get_nextval(T, nextval) 求模式串优化后的nextval数组
* int Index_KMP(S, T) KMP算法求出串S中第一次出现串T的位置 返回值为定位串T的位置,如果没有找到返回0
*
*********************************************************************************************************************************/

// 串的顺序存储 定长顺序存储(静态数组)
typedef struct SString{
char ch[MAXLEN]; // 每个分量存储一个字符
int length; // 串的实际长度
}SString;

// 串的顺序存储 可拓展长度顺序存储(指针数组)
typedef struct HString{
char *ch; // 按串长分配存储区,ch指向串的基地址
int length; // 串的长度
}HString;
//HString S; S.ch = (char *)malloc(MAXLEN*sizeof(char)); S.length = 0;

// 串的链式存储
typedef struct StringNode{
char ch; // 每个结点存1字符,若要提高存储密度,则可设置为多个字符数组
struct StringNode *next;
}StringNode, *Node;

// 赋值操作
bool StrAssign(SString &T, char *ch){
int i = 1;
while(ch[i] != '\0'){
T.ch[i] = ch[i];
i++;
}
T.length = i;
return true;
}

// 复制操作
bool StrCopy(SString &T, SString S){
int i = 1;
while(S.ch[i] != '\0'){
T.ch[i] = S.ch[i];
i++;
}
T.length = i;
return true;
}

// 判空
bool StrEmpty(SString S){
return S.length == 0;
}

// 求长度
int StrLength(SString S){
return S.length;
}

// 清空
bool ClearString(SString &S){
S.length = 0;
return true;
}

// 销毁
bool DestroyString(SString &S){
S.length = 0;
return true;
}

// 串连接
bool Concat(SString &T, SString S1, SString S2){
int i = 1;
while(S1.ch[i] != '\0'){
T.ch[i] = S1.ch[i];
i++;
}
while(S2.ch[i] != '\0'){
T.ch[i] = S2.ch[i];
i++;
}
T.length = i;
return true;
}

// 求子串
bool SubString(SString &Sub, SString S, int pos, int len){
if(pos < 1 pos > S.length len < 0 len > S.length - pos + 1){ // 子串位置不合法
return false;
}
Sub.length = len;
for(int i = 0; i < len; i++){
Sub.ch[i] = S.ch[pos - 1 + i];
}
return true;
}

// 比较操作
int StrCompare(SString S, SString T){
for(int i = 0; i < S.length && i < T.length; i++){
if(S.ch[i] != T.ch[i]){
return S.ch[i]-T.ch[i];
}
}
return S.length - T.length;
}

// 定位操作
int Index(SString S, SString T){
int i = 1, n = S.length, m = T.length;
SString Sub;
while(i <= n - m + 1){
if(SubString(Sub, S, i, m) && StrCompare(Sub, T) == 0){
return i;
}
i++;
}
}

// 朴素模式匹配
int Index2(SString S, SString T){
int k = 1; // 当前匹配的字符位置
int i = k, j = 1;
while(i <= S.length && j <= T.length){
if(S.ch[i] == T.ch[j]){
i++; // 继续比较后续字符
j++;
}else{
k++; // 匹配失败,向后移动匹配字符位置
i = k;
j = 1;
}
}
if(j > T.length){
return k;
}else{
return 0;
}
}

// KMP算法:朴素模式算法优化
int Index_KMP_Need_Next(SString S, SString T, int next[]){ // 传入next数组
// 例:google的next数组为next[7] = {0, 0, 1, 1, 1, 2, 1}
int i = 1, j = 1;
while(i <= S.length && j <= T.length){
if(j == 0 S.ch[i] == T.ch[j]){ // 通过j==0来判断是否是第一位不相符,然后i,j都加一以至于可以i向后移,j归为1
i++;
j++;
}else{
j = next[j];
}
}
if(i > T.length){
return i-T.length;
}else{
return 0;
}
}

// 求模式串T的next数组
void get_next(SString T, int next[]){
int i = 0, j = 0;
next[1] = 0;
while(i < T.length){
if(j == 0 T.ch[i] == T.ch[j]){
++i;
++j;
// 若pi等于pj,则next[j+1] = next[j] + 1
next[i] = j;
}else{
j = next[j];
}
}
}

// next数组优化为nextval数组
void get_nextval(SString T, int nextval[]){
int *next = new int[T.length+1];
get_next(T, next);
nextval[1] = 0;
for(int j = 2; j <=T.length; j++){
if(T.ch[j] == T.ch[next[j]]){
nextval[j] = nextval[next[j]];
}else{
nextval[j] = next[j];
}
}
delete[] next;
}

// KMP算法
int Index_KMP(SString S, SString T){
int i = 1, j = 1;
int *next = new int[T.length+1];
get_next(T, next); // 求模式串T的next数组 时间复杂度O(m)
while(i <= S.length && j <= T.length){ // 时间复杂度O(n)
if(j == 0 S.ch[i] == T.ch[j]){
i++;
j++; // 继续比较后继字符
}else{
j = next[j]; // 模式串向右移动
}
}
delete[] next;
if(j>T.length){
return i-T.length; // 匹配成功返回匹配的位置
}else{
return 0;
}
}

数据结构——串
https://blog.zhuanjie.ltd/2022/02/19/sstring/
作者
转接
发布于
2022年2月19日
许可协议