串
串
串的概念
内容受限(只能是字符)的线性表;串中逻辑关系与线性表相同
零个或多个字符组成的有限序列
(串名)S="(串值)a1,a2,...,an" ((串长)n>=0)
空串用∅表示
-
子串:一个串中任意个连续字符组成的子序列(含空串)称为该串的子串
-
真子串:不包含自身的所有子串
-
主串:包含子串的串
-
字符位置:字符在序列中的序号为该字符在串中的位置
-
子串位置:子串第一个字符在主串中的位置
-
空格串:由一个或多个空格组成的串
-
串相等:当且仅当两个串的长度相等并且各个对应位置上的字符都相同,这两个串才是相等的
所有的空串都是相等的
串的抽象数据类型定义
ADT String{
数据对象:D=ai|ai属于Characterset,i=1,2,...,n,n>=0}
数据关系:R1=<ai-1,ai>|ai-1,ai属于D,i=2,3,...,n}
基本操作:
StrAssign (&T,chars)
StrCompare (S,T)
StrLength (S)
Concat(&T,S1,S2)
SubString(&Sub,S,pos,len)
StrCopy(&T,S)
StrEmpty(S)
ClearString(&S)
lndex(S,T,pos)
Replace(&S,T,V)
Strlnsert(&S,pos,T)
StrDelete(&S,pos,len)
DestroyStrina(&S)
......
}ADT String
顺序串
顺序串的定义
#define MAXLEN 255
typedef struct{
char ch[MAXLEN+1]; //存储串的一位数组
int length; //串的当前长度
}SString;
串的模式匹配
确定主串中子串第一次出现的位置
算法应用:
- 搜索引擎
- 拼写检查
- 语言翻译
- 数据压缩
算法种类:
-
BF算法/简单匹配算法(brute-force):暴力破解,采用穷举法
-
匹配失败:
- 主串:i=i-j+2(回溯)
- 子串:j=1(重头开始)
-
匹配成功:
return i-子串长度
int index_BF1(SString S,SString T){ int i=1,j=1; while (i<=S.length&&j<=T.length){ if(S.ch[i]==T.ch[j]){ i++; j++; } else { i=i-j+2; j=1; } } if(j>=T.length) return i-T.length; else return 0; } int index_BF2(SString S,SString T,int pos){ int i=pos,j=1; while (i<=S.length&&j<=T.length){ if(S.ch[i]==T.ch[j]){ i++; j++; } else { i=i-j+2; j=1; } } if(j>=T.length) return i-T.length; else return 0; }
时间复杂度是O(n*m)
-
-
KMP算法:速度快
主串S的指针i不必回溯,可提速到O(n+m)
例:
i 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 模式串 a b c a a b b c a b c a a b d a b j=next[i] 0 1 1 1 2 2 3 1 1 2 3 4 5 6 7 1 2 void get_next(SString T,int next[]){ int i=1,j=0; next[1]=0; while (j<T.length){ if(j==0||T.ch[i]==T.ch[j]){ next[++i]=++j; } else j=next[j]; } } int index_KMP(SString S,SString T,int pos,int next[]){ int i=pos,j=1; while(i<S.length&&j<T.length){ if(j==0||S.ch[i]==S.ch[j]){ i++; j++; } else j=next[j]; } if(j>T.length) return i-T.length; else return 0; }
求nextval:
-
第一位的nextval一定是0
-
第i位字符与第next[i]位的字符进行比较:
- 不同:nextval=next值
- 相同:nextval=第next[i]位的next值
void get_nextval(SString T,int nextval[]){ int i=1,j=0; int nextval[1]=0; while(i<T.length){ if(j==0||T.ch[i]==T.ch[j]){ ++i; ++j; if(T.ch[i]!=T.ch[j]) nextval[i]=j; else nextval[i]=nextval[j]; } else j=nextval[j]; } }
-
链串
块链的定义
#define CHUNKSIZE 80 //定义块的大小
typedef struct Chunk{
char ch[CHUNKSIZE];
struct Chunk *next;
}Chunk;
typedef struct {
Chunk *head,*tail; //串的头指针和尾指针
int curlen; //串的当前长度
}LString; //字符串的块链结构
串的应用
-
病毒感染监测(字符串的匹配):然后检测某种病毒DNA序列是否在患者的DNA序列中出现过,如果出现过,则此人感染了该病毒,否则没有感染
例:假设病毒的DNA序列为baa(人的DNA序列是线性;病毒DNA序列是环状,因此病毒DNA:baa,aab,aba)可将病毒的DNA存储两次遍历3(n,n为病毒DNA长度)次
患者1的DNA序列为aaabbba,则感染
患者2的DNA序列为babbba,则未感染