860 likes | 966 Views
本节内容有难度,考试不做要求。但是某些学校的考研课要考。主要强调思想,程序不多说。. 4.2.2 堆分配存储表示 这种存储方式和前面的顺序表相仿,采用动态数组来存储串,数组的大小会随着串的变化而进行调整。 下面实现堆表示的串及其基本操作:. #include <iostream> using namespace std; struct SString// 串 { char *s;// 存储串中字符 int str_len; };. int strlen(SString s)// 求串的长度 { return s.str_len; } ///
E N D
本节内容有难度,考试不做要求。但是某些学校的考研课要考。主要强调思想,程序不多说。本节内容有难度,考试不做要求。但是某些学校的考研课要考。主要强调思想,程序不多说。
4.2.2堆分配存储表示 这种存储方式和前面的顺序表相仿,采用动态数组来存储串,数组的大小会随着串的变化而进行调整。 下面实现堆表示的串及其基本操作:
#include <iostream> using namespace std; struct SString//串 { char *s;//存储串中字符 int str_len; };
int strlen(SString s)//求串的长度 { return s.str_len; } /// int str_assign(SString &s1,char *s2) { int len=strlen(s2);//假定s2的长度不会超过MAXSTRLEN s1.str_len=len; s1.s=new char[len+1];//第0个单元不用 for(int i=1;i<=len;i++) s1.s[i]=s2[i-1]; return 1; }
int str_insert(SString &s,int i,char a)//在串中插入一个字符 { int len=strlen(s); if(i<1 || i>len+1) return 0;//越界 char *temp=new char[len+1+1];//0单元不用,又增加一个 for(int j=1;j<=i-1;j++) temp[j]=s.s[j]; temp[i]=a; for(j=i+1;i<=len;j++,i++) temp[j]=s.s[i]; s.str_len++; delete []s.s; s.s=temp; return 1; }
int str_copy(SString &s1,SString &s2) {//将s2中字符串拷贝到s1中 char *temp=new char[s2.str_len]; //delete []s1.s; //s1.s=temp; for(int i=1;i<=strlen(s2);i++) temp[i]=s2.s[i]; s1.str_len=s2.str_len ; delete []s1.s; s1.s=temp; return 1; }
void str_cat(SString &s0,SString s1,SString s2) {//将s2连接到s1的后面,结果存放在s0中,若空间不够则截断 s0.s=new char[s1.str_len+s2.str_len+1]; //0单元不用 s0.str_len=s1.str_len+s2.str_len; for(int i=1;i<=s1.str_len;i++) s0.s[i]=s1.s[i]; for(int j=1;j<=s2.str_len;j++,i++) s0.s[i]=s2.s[j]; }
int str_index(SString s,SString t,int pos) {//从第pos个位置开始查找t在s中出现的第一个位置 if(pos<1) return 0; int start=pos,end=s.str_len-t.str_len+1; for(int i=start;i<=end;i++) { for(int j=1,k=i;j<=t.str_len;j++,k++) { if(s.s[k]!=t.s[j]) break; } if(j>t.str_len)return i; } return 0; }
void print(SString &s) { for(int i=1;i<=strlen(s);i++) cout<<s.s[i]; cout<<endl; } //////////
int main(int argc, char* argv[]) { SString a,b; str_assign(a,"abc"); str_assign(b,"def"); print(a); print(b); ::str_insert(a,2,'m'); print(a); ::str_copy(a,b); print(a); str_assign(a,"aaa"); str_assign(b,"bbb"); print(a);print(b); SString c; str_cat(c,a,b); print(c); str_assign(a,"abcdefghijklmn"); str_assign(b,"defg"); print(a); print(b); cout<<str_index(a,b,1)<<endl; return 0; }
4.3 串的模式匹配算法 4.3.1 传统的模式匹配算法(前面已经介绍) 4.3.2 KMP算法 先看KMP算法的执行过程,然后来解释其思想
在主串s=“acabaabaabcacaabc”中 查找模式串t=“abaabcac”
j a a c a b a a b a b c a c c a a b i 2 4 a 0 a 1 2 b 1 1 3 a c 6 3 a 7 1 5 2 b 8 c 2 模式串 Next[j]
i j a a c a b a a b a b c a c c a a b i 2 4 a 0 a 1 2 b 1 3 1 a 3 6 c a 1 7 5 2 b 8 2 c 模式串 Next[j] 不等,根据Next[j],让模式串回溯到1,即j=1
j a a c a b a a b a b c a c c a a b i 2 4 a 0 a 1 2 b 1 3 1 a 3 6 c a 1 7 5 2 b 8 2 c 模式串 Next[j] 不等,根据Next[j],此时next[j]=0,令j=1,i后移
j a a c a b a a b a b c a c c a a b i 2 4 a 0 a 1 2 b 1 1 3 a c 6 3 a 7 1 5 2 b 8 c 2 模式串 Next[j]
j a a c a b a a b a b c a c c a a b i 2 4 a 0 a 1 2 b 1 1 3 a c 6 3 a 7 1 5 2 b 8 c 2 模式串 Next[j]
j a a c a b a a b a b c a c c a a b i 2 4 a 0 a 1 2 b 1 1 3 a c 6 3 a 7 1 5 2 b 8 c 2 模式串 Next[j]
j a a c a b a a b a b c a c c a a b i 2 4 a 0 a 1 2 b 1 1 3 a c 6 3 a 7 1 5 2 b 8 c 2 模式串 Next[j]
j a a c a b a a b a b c a c c a a b i 2 4 a 0 a 1 2 b 1 1 3 a c 6 3 a 7 1 5 2 b 8 c 2 模式串 Next[j]
j a a c a b a a b a b c a c c a a b i 2 4 a 0 a 1 2 b 1 3 1 a 3 6 c a 1 7 5 2 b 8 2 c 模式串 Next[j] 不等,根据Next[j],让模式串回溯到3,即j=3
j a a c a b a a b a b c a c c a a b i 2 4 a 0 a 1 2 b 1 1 3 a c 6 3 a 7 1 5 2 b 8 c 2 模式串 Next[j]
j a a c a b a a b a b c a c c a a b i 2 4 a 0 a 1 2 b 1 1 3 a c 6 3 a 7 1 5 2 b 8 c 2 模式串 Next[j]
j a a c a b a a b a b c a c c a a b i 2 4 a 0 a 1 2 b 1 1 3 a c 6 3 a 7 1 5 2 b 8 c 2 模式串 Next[j]
j a a c a b a a b a b c a c c a a b i 2 4 a 0 a 1 2 b 1 1 3 a c 6 3 a 7 1 5 2 b 8 c 2 模式串 Next[j]
j a a c a b a a b a b c a c c a a b i 2 4 a 0 a 1 2 b 1 1 3 a c 6 3 a 7 1 5 2 b 8 c 2 模式串 Next[j]
j a a c a b a a b a b c a c c a a b i 2 4 a 0 a 1 2 b 1 3 1 a 3 6 c a 1 7 5 2 b 8 2 c 模式串 Next[j] 成功
可以看出KMP算法比传统的算法要快得多。其中的关键是模式串的Next函数怎样求。可以看出KMP算法比传统的算法要快得多。其中的关键是模式串的Next函数怎样求。 下面看一下推导过程。 假设主串为:“s1s2….sn”,模式串为:“p1p2…..pm” 假定在某个时刻,si和pj不相等,那么此时p(j-1)到p1跟s中相应位置字符相同,所以有下面的等式: p1p2…p(j-1)=s(i-j+1)….s(i-1) 此时假定模式串回溯到第k个位置就能够继续向下进行比较,那么也有等式: p1p2….pk=s(i-k+1)….s(i) -------〉 p1p2….p(k-1)=s(i-k+1)….s(i-1) 此时k<j
即有下面关系: 所以有 p(j-k+1)….p(j-1)=p1….p(k-1)
因为k<j;从上面式子观察可得,k>=2,则j>=3。 令j=1时,k=0;可以理解为:当第一个字符不相等时,主串的指针后移一个位置,模式串从第一个字符开始。那么也可以理解为模式串回溯到第0个字符和主串进行比较,因为不存在第0个字符,所以跟上面的意思一样。 令j=2时,k=1。即当第二个字符不等时,模式串回溯到第1个字符进行比较。 其他情况下,next[j]=k=Max{k| p(j-k+1)….p(j-1)=p1….p(k-1)},比字符串长度多1。