串的定义及朴素的模式匹配算法
Posted Laccoliths
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了串的定义及朴素的模式匹配算法相关的知识,希望对你有一定的参考价值。
1 串(String)的定义
早先在计算机在被发明时,主要作用是做一些科学和工程的工作,也就是类似于现在的计算器,只不过是比计算器功能更强大,速度更快一些。但是后来随着社会和技术的发展,在计算机上作废树脂处理的工作越来越多,使得我们不得不引入对字符的处理,于是就有了我们今天字符串的概念。
串的定义:串是由零个或多个字符组成的有限序列,又叫字符串。
一般记为$s=”a_1a_2···a_n (n\\geq0)"$,其中,s是串的名称,用双引号括起来的字符序列是串的值,引号不属于串的内容。$a_i($ $1 \\leq i \\leq n )$可以是字母、数字或其他字符,$i$就是该字符在串中的位置。
串中的字符数目$n$称为串的长度,零个字符的串称为空串 (null string)。所谓序列说明串的相邻字符之间具有前驱和后继的关系。
2 串的比较
串的比较是通过组成串的字符之间的编码来进行的,而字符的编码指的是字符在对应字符集中的序号。
给定两个串:$s=”a_1a_2···a_n (n\\geq0)"$,$t=”b_1b_2···b_m (m\\geq0)"$,当且仅当$n=m$时,且$a_1=b_1$,$a_2=b_2$,·····,$a_n=b_m$,我们认为$s=t$。
那么对于两个串不相等时,如何判定它们的大小呢?
给定两个串:$s=”a_1a_2···a_n (n\\geq0)"$,$t=”b_1b_2···b_m (m\\geq0)"$,当满足以下条件之一时,$s\\leq t$:
-
$n<m$,且$a_i=b_i(i=1,2,···,n)$
-
存在某个$k\\leq min(m,n)$,且$a_i=b_i(i=1,2,···,k-1),a_k<b_k$
比如“silly”和“stupid”在计算中的大下取决于它们挨个字母的前后顺序,它们的第一个字母是“s”,我们认为不存在大小差异,而第二个字母,由于“i”字母比“t”字母要考前,所以“i”<“t”,于是我们说“silly”小于“stupid”。
3 串的抽象数据类型
对于串的基本操作与线性表是有很大差别的。线性表更关注的是单个元素的操作,比如查找一个元素、插入或删除一个元素,但串中更多的是查找子串位置、得到指定位置子串、替换子串等操作。
串的伪代码定义如下:
ADT 串(string)
Data
串中元素仅由一个字符组成,相邻元素具有前驱和后继关系。
Operation
StrAssign(T,*chars):生成一个其值等于字符串常量chars的串T。
StrCopy(T,S):串S存在,由串S复制到串T。
ClearString(S):串S存在,将串清空。
StringEmpty(S):若串S为空,返回true,否则返回false。
StrLength(S):返回串S的元素个数,即串的长度。
StrCompare(S,T):若S>T,返回值大于0,若S=T,返回值等于0,若S<T,返回值小于0。
Concat(T,S1,S2):用T返回S1和S2连接而成的新串。
SubString(Sub,S,pos,len):S存在,1≤pos≤StrLength(S),且 0≤1en≤StrLength(S)-pos+1,用Sub返回串S的第 pos个字符起长度为1en的子串。
Index(S,T,pos):串S和T存在,T是非空串,1≤pos≤StrLength(S)。若主串S中存在和 串T值相同的子串,则返回它在主串S中第pos个字符之后第一次出现的位 置,否则返回0。
Replace(S,T,V):串S,T,V存在,T是非空串。用V替代主串中S中出现的所有与T相等的不 重叠的子串。
StrInsert(S,pos,T):串S和T存在,1≤pos≤StrLength(S)+1。在串S的第pos个字符 之前插入串T。
StrDelete(S,pos,len):串S存在,1≤pos≤StrLength(S)+1。从串S中删除第pos个字 符起长度为len的子串。
endADT
Index定位字符位置算法实现:
/* 返回子串T在主串S中第pos个字符之后的位置。若不存在,则函数返回值为0。 */
/* 其中,T非空,1≤pos≤StrLength(S)。 */
int Index(String s, String T, int pos)
int n,m,i;
String sub;
if(pos>0)
n = StrLength(S); // 得到主串S的长度
m = StrLength(T); // 得到子串T的长度
i = pos;
while(i<=n-m+1)
SubString(sub,S,i,m); // 取子串第i个位置开始长度与T相等的字串给sub
if(StrCompare(sub,T) != 0) // 如果两串不相等
++i;
else // 如果两串相等
return i; // 返回i值
return 0; // 若无子串与T相等,返回0
StrLength获取字符串长度算法实现:
/* 返回串的元素个数 */
int StrLength(String S)
return S[0];
SubString寻找字符串子串算法实现:
/* 用Sub返回串S的第pos个字符起长度为len的子串。 */
Status SubString(String Sub,String S,int pos,int len)
int i;
if(pos<1||pos>S[0]||len<0||len>S[0]-pos+1)
return ERROR;
for(i=1;i<=len;i++)
Sub[i]=S[pos+i-1];
Sub[0]=len;
return OK;
Strcompare比较两字符串在计算机中大小算法实现:
/* 初始条件: 串S和T存在 */
/* 操作结果: 若S>T,则返回值>0;若S=T,则返回值=0;若S<T,则返回值<0 */
int StrCompare(String S,String T)
int i;
for(i=1;i<=S[0]&&i<=T[0];++i)
if(S[i]!=T[i])
return S[i]-T[i];
return S[0]-T[0];
4 朴素的模式匹配算法
对于模式匹配算法我们利用最多的就是去找一个单词在一篇文章(相当于一个大字符串)的定位问题。 子串的定位操作通常称做串的模式匹配,最重要的就是去找一个单词在一篇中的定位问题。
假设要从主串S=“goodgoogle”中,找到T=“google”这个子串的位置,下面是进行的步骤。
-
主串S第—位开始, S与T前三个字母都匹配成功,但S第四个字母是d,而T的是g。第一位匹配失败。
-
主串S第二位开始,主串S首字母是o,要匹配的T首字母是g,匹配失败。
::: hljs-center
:::
-
主串S第三位开始,主串S首字母是o,要匹配的T首字母是g,匹配失败。
-
主串S第四位开始,主串S首字母是d,要匹配的T首字母是g,匹配失败。
-
主串S第五位开始,S与T,6个字母全匹配,匹配成功。
简单的说,就是对主串的每个字符作为子串开头,与要匹配的字符串进行匹配,对主串做大循环,每个字符开头做T的长度的小循环,直到匹配成功或全部遍历为止。
模式匹配算法Index:
/* 返回子串T在主串S中第pos个字符之后的位置。若不存在,则函数返回值为0。 */
/* 其中,T非空,1≤pos≤StrLength(S)。 */
int Index(String S, String T, int pos)
int i = pos; /* i用于主串S中当前位置下标值,若pos不为1,则从pos位置开始匹配 */
int j = 1; /* j用于子串T中当前位置下标值 */
while (i <= S[0] && j <= T[0]) /* 若i小于S的长度并且j小于T的长度时,循环继续 */
if (S[i] == T[j]) /* 两字母相等则继续 */
++i;
++j;
else /* 指针后退重新开始匹配 */
i = i-j+2; /* i退回到上次匹配首位的下一位 */
j = 1; /* j退回到子串T的首位 */
if (j > T[0])
return i-T[0];
else
return 0;
时间复杂度:$O((n-m+1)*m)$
以上是关于串的定义及朴素的模式匹配算法的主要内容,如果未能解决你的问题,请参考以下文章