4数据结构之串.docx
《4数据结构之串.docx》由会员分享,可在线阅读,更多相关《4数据结构之串.docx(7页珍藏版)》请在冰豆网上搜索。
4数据结构之串
第四章串
4.1串的定义和运算
一、串的定义
串也称字符串,是由n(n≥0)个字符组成的有限序列,记为:
s=”a1a2a3……an”
ai(1≤i≤n)可以是字母、数字或其它字符。
请注意,空串与空格串的区别。
我们将一个串中若干个相连字符组成的子序列称为该串的子串。
包含子串的串称这为主串。
例如,两个串t=”struct”和s=”datastructure”,称t是s的子串。
二、串的运算
设t,s,s1,s2均为串名。
1.串复制操作
StrCopy(t,s),由串s复制得串t。
例如:
s=”datastructure”,执行StrCopy(s,t)后,t=”datastructure”。
2.联结操作
Concat(t,s1,s2),用串s1和串s2联结而成的一个新串t。
例:
s1=”data”,s2=”structure”,
执行Concat(t,s1,s2)后,t=”datastructure”。
联结函数符合结合律,不符合交换律。
即:
Concat(t,s1,s2,s3)
=Concat(t,Concat(t,s1,s2),s3))
=Concat(t,s1,Concat(t,s2,s3))
3.求串的长度:
StrLength(s),得串s中的元素个数
例如:
s=”datastructure”,则串的长度为14。
4.求子串操作
SubStr(s,i,m,t),求得由主串s的第i个字符开始,长度为m子串t。
例如:
s=”datastructure”,执行SubString(s,6,6,t),得t=”struct”。
5.判两个串是否相等:
StrEqual(s,t),当两个串s和t的长度相等,且两个串对应位置的每个字符都相等,返回TRUE,否则返回FLASE。
例:
s=”datastructure”,t=”datastructure”,执行StrEqual(s,t),得TURE。
6.求子串在串中的序号(又称定位)
Index(s,t),若主串s中存在和串t值相同的子串,则返回它在主串s中第1个字符之后第一次出现的位置;否则函数值为0。
如:
s=”datastructure”,t=”struct”,执行Index(s,t),返回6。
s=”datastructure”,t=”date”,执行Index(s,t),返回0。
7.置换操作
Replace(s,t,v),若主串s中存在和串t值相同的子串,则用v来替换。
注意用v替换主串s中出现的所有与t相等的不重叠的子串。
例如:
s=”abcabcababcaab”,t=”cab”,v=”c”,执行Replace(s,t,v),得:
s=”abccabcaab”。
4.2串的存储结构
一、行结构
unsignedcharString[256];
//用户可在255以内定义最大串长
//0号单元存放串的长度
这种存储结构是一种定长的顺序存储结构,较适应于源程序等的存储。
二、堆结构
(1)串值的存储
structstrstore{
char*ch;
//若是非空串,则按串长分配存储区,否则ch为NULL
intpos;
//pos是空闲区的首地址(已占用空间)的长度
};
其中:
pos是空闲区的首地址(已占用空间)的长度,s1和s2是串名,17和15是子串的长度
(2)串名的存储
串名
开始地址
串的长度
串名
开始地址
结束地址
串名
开始地址
开始地址
例:
文本编辑P
(1)串值的存储
(2)串名的存储
串名
开始地址
串的长度
1
1000
40
2
1040
16
3
1056
35
4
1091
14
5
1105
1
(3)操作:
插入、删除、排版等
4.3模式匹配
s=“s1s2,……sn”,t=“t1t2……tm”,m≤n
在s中是否存在长度为m的子串“sisi+1……si+m-1”,使得“sisi+1……si+m-1”=“t1t2……tm”。
称s为文本,t为模式。
s=“s1s2,…sisi+1……si+m-1…sn”,
“t1t2……tm”
4.3.1串匹配(搜索)算法
一、基本思想
从文本s的第一个字符起和模式t的第一个字符进行比
较,若相等,则继续逐个比较后续字符,否则从文本的第二个字符起重新和模式的字符进行比较。
依次类推,直至
si=t1,si+1=t2,……,si+m-1=tm
止,则称匹配成功,函数值为i,否则称匹配不成功,函数值为零。
二、示例
s="abaabaaccabaabcabc",
t="abaabca"
第一趟
文本abaabaaccabaabcabc
i=1→6
abaabc
j=1→6
第二趟
文本abaabaaccabaabcabc
i=2
a
j=1
第三趟
文本abaabaaccabaabcabc
i=3→4
ab
j=1→2
第四趟
文本abaabaaccabaabcabc
i=4→8
abaab
j=1→5
第五趟
文本abaabaaccabaabcabc
i=5
a
j=1
第六趟
文本abaabaaccabaabcabc
i=6→7
ab
j=1→2
第七趟
文本abaabaaccabaabcabc
i=7→8
ab
j=1→2
第八趟
文本abaabaaccabaabcabc
i=8
a
j=1
第九趟
文本abaabaaccabaabcabc
i=9
a
j=1
第十趟
文本abaabaaccabaabcabc
i=10→17
abaabca
j=1→8
在i=10,j=8时匹配成功,返回10。
模式匹配算法
intIndex(s,t){
//返回子串t在主串S中的位置。
若不存在,则函数值为0。
i=1;j=1;
while(i<=s[0]&&j<=t[0])
if(s[i]==t[j])
{++i;++j;}//继续比较后继字符
else
{i=i-j+2;j=1;}//i指针回溯,重新开始匹配
if(j>t[0])returni-t[0];elsereturni;
}//Index
O(m*n)。
问题:
模式匹配算法的时间复杂度能否进一步的改善呢?
3.2KMP(Knuth-Morris-Pratt)算法
解决的问题是:
向右“滑动”多少呢?
考察abaabaaccabaabcabc
abaabc
abaabc
结论:
模式匹配过程中没有回溯。
第一趟
文本abaabaaccabaabcabc
i=1→6
abaabc
j=1→6
第二趟
文本abaabaaccabaabcabc
i=6→8
(ab)aab
j=3→5
第三趟
文本abaabaaccabaabcabc
i=8
(a)b
j=2
第四趟
文本abaabaaccabaabcabc
i=8
a
j=1
第五趟
文本abaabaaccabaabcabc
i=9
a
j=1
第六趟
文本abaabaaccabaabcabc
i=10→17
abaabca
j=1→8
intKMP(SStrings,SStringt){
i=1;j=1;
while(i<=s[0]-t[0]+1&&j<=t[0])
if(j=0||s[i]==t[j])
++i;++j;//继续比较后继字符
else
j=next(j);//模式串向右移动
if(j>t.len)returni-t[0];
elsereturn0;
}//KMP
O(m+n)
模式串的next函数的定义:
J
1
2
3
4
5
6
7
T
a
b
a
a
b
c
a
next[j]