串的定义及朴素的模式匹配算法

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$:

  1. $n<m$,且$a_i=b_i(i=1,2,···,n)$

  2. 存在某个$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”这个子串的位置,下面是进行的步骤。

  1. 主串S第—位开始, S与T前三个字母都匹配成功,但S第四个字母是d,而T的是g。第一位匹配失败。

  2. 主串S第二位开始,主串S首字母是o,要匹配的T首字母是g,匹配失败。

    ::: hljs-center

:::

  1. 主串S第三位开始,主串S首字母是o,要匹配的T首字母是g,匹配失败。

  2. 主串S第四位开始,主串S首字母是d,要匹配的T首字母是g,匹配失败。

  3. 主串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)$

以上是关于串的定义及朴素的模式匹配算法的主要内容,如果未能解决你的问题,请参考以下文章

串的模式匹配算法之kmp

朴素模式匹配算法(C语言)

字符串模式匹配KMP算法

串的匹配:朴素匹配&amp;KMP算法

图解字符串的朴素模式匹配算法

字符串的朴素模式匹配算法