第四章串
第一节串的概念和存储结构
1.串的概念
由0个或多个字符组成的有效序列,一般记作
$$
S=‘a_1a_2a_3…a_n’~~~(n≥0)
$$
2.串的存储结构和基本算法的实现
(1)定长顺序存储表示
1 2 3 4 5
| #define MAXLEN 255 typedef struct{ char ch[MAXLEN]; int length; }SString;
|
(2)堆分配存储表示
1 2 3 4
| typedef struct{ char *ch; int length; }HString;
|
(3)基本操作
1 2 3 4 5 6 7 8 9 10
| StrAssign(&T,chars):赋值操作。把串T赋值为chars。 StrCopy(&T,S):复制操作。由串S复制得到串T。 StrEmpty(S):判空操作。若S为空串,则返回TRUE,否则返回FALSE。 StrLength(S):求串长。返回串S的元素个数。 ClearString(&S):清空操作。将S清为空串。 Concat(&T,S1,S2):串联接。用T返回由S1和S2联接而成的新串 SubString(&Sub,S,pos,len):求子串。用Sub返回串S的第pos个字符起长度为len的子串。 Index(S,T):定位操作。若主串S中存在与串T值相同的子串,则返回它在主串S中第一次出现的位置;否则函数值为0。 StrCompare(S,T):比较操作。若S>T,则返回值>0;若S=T,则返回值=0;若S<T,则返回值<0。 DestroyString(&S):销毁中。将串S销毁。
|
第二节串的匹配算法
1.BF算法(简单模式匹配算法)
时间复杂度:最好O(n),最坏O(nm)
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
| #include<iostream> using namespace std; int BF(string S,string T,int pos) { int i = pos; int j = 1; while( i <= S.size() && j <= T.size() ) { if( S[i-1] == T[j-1] ) { i++; j++; } else { i = i-j+2; j = 1; } } if( j > T.size() ) return i - T.size(); return 0; } int main() { int pos; string S,T; while( true ) { cout<<"请输入母串:"; cin>>S; cout<<"请输入模式串:"; cin>>T; cout<<"请输入在母串中开始寻找的位置(小于等于"<<S.size()<<"):"; cin>>pos; while ( pos > S.size() ) { cout<<"请重新输入在母串中开始寻找的位置(小于等于"<<S.size()<<"):"; cin>>pos; } cout<<"模式串在自母串第 "<<pos<<" 位开始出现的位置为 "<<BF(S,T,pos)<<endl<<endl; } }
|
2.KMP算法
(1)next数组
以‘ababa’举例说明:
- 'a’的前缀和后缀都是空集,最长相等前后缀长度为0;
- 'ab’的前缀为{a},后缀为{b},{a}且{b}=空集,最长相等前后缀长度为0;
- 'aba’的前缀是{a,ab},后缀是{a,ba},{a,ab}且{a,ba}={a},最长相等前后缀长度为1;
- 'abab’的前缀是{a,ab,aba},后缀是{a,ba,bab},{a,ab,aba}且{a,ba,bab}={a},最长相等前后缀长度为1;
- 'ababa’的前缀是{a,ab,aba,abab},后缀是{a,ba,aba,baba},{a,ab,aba,abab}且{a,ba,aba,baba}={a,aba},最长相等前后缀长度为3;
时间复杂度:O(n+m);优点:主串不回溯
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
| #include <stdio.h> #include <string.h> void Next(char*T,int *next){ int i=1; next[1]=0; int j=0; while (i<strlen(T)) { if (j==0||T[i-1]==T[j-1]) { i++; j++; next[i]=j; }else{ j=next[j]; } } } int KMP(char * S,char * T){ int next[10]; Next(T,next); int i=1; int j=1; while (i<=strlen(S)&&j<=strlen(T)) { if (j==0 || S[i-1]==T[j-1]) { i++; j++; } else{ j=next[j]; } } if (j>strlen(T)) { return i-(int)strlen(T); } return -1; } int main() { int i=KMP("ababcabcacbab","abcac"); printf("%d",i); return 0; }
|
(2)nextval数组
j |
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
模式串T |
a |
b |
a |
b |
a |
a |
a |
b |
a |
next |
0 |
1 |
1 |
2 |
3 |
4 |
2 |
2 |
3 |
nextval |
0 |
1 |
0 |
1 |
0 |
4 |
2 |
1 |
0 |