04 串

04 串

在这里插入图片描述

  1. 定义

    串(String)是由零个或多个字符组成的有限序列,又名叫字符串。

     ADT 串(string)
     Data
            串中元素仅由一个字符组成,相邻元素具有前驱和后继关系
     Operation
           StrAssign(T,*chars):生成一个其值等于字符串常量chars的串T。
           StrCopy(T,S):串S存在,由串S复制得串T。
           ClearString(S):串S存在,将串清空。
           StringEmpty(S):若串为空,则返回true,否则返回false。
           StrLength(S):返回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<=len<=Strlength(S)-pos+1.
                                              用Sub返回串S的第pos个字符起长
                                              度为len的子串。
           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。
           SteDelete(S,pos,len):串S存在,1<=pos<=StrLength(s)-len+1.从串
                                        S中删除第pos个字符起长度为len的子串。
    
  2. 顺序存储结构

  3. 链式存储结构

  4. 朴素的模式匹配算法:最坏情况的时间复杂度为O((n-m+1)*m)

子串的定位操作通常称做串的模式匹配

	/* 朴素的模式匹配法 */
	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;
	}
  1. KMP模式匹配算法

    1. 原理
    2. 实现

    对于get_next函数来说,若T的长度为m,因只涉及到简单的单循环,其时间复杂度为O(m),而由于i值不回溯,使得index_KMP算法效率得以提高,while循环的时间复杂度为O(n)。因此,整个算法的时间复杂度为O(m+n)。相较于朴素模式匹配算法的O((n-m+1)*m)来说,是要好一些。但这里也需要强调,KMP算法仅当模式与主串之间存在许多“部分匹配”的情况下才体现出它的优势,否则两者差异并不明显。

     	/* 通过计算返回子串T的next数组。 */
     	void get_next(String T, int *next) 
     	{
     		int i,j;
     	  	i=1;
     	  	j=0;
     	  	next[1]=0;
     	  	while (i<T[0])  /* 此处T[0]表示串T的长度 */
     	 	{
     	    	if(j==0 || T[i]== T[j]) 	/* T[i]表示后缀的单个字符,T[j]表示前缀的单个字符 */
     			{
     	      		++i;  
     				++j;  
     				next[i] = j;
     	    	} 
     			else 
     				j= next[j];	/* 若字符不相同,则j值回溯 */
     	  	}
     	}
     	
     	/* 返回子串T在主串S中第pos个字符之后的位置。若不存在,则函数返回值为0。 */
     	/*  T非空,1≤pos≤StrLength(S)。 */
     	int Index_KMP(String S, String T, int pos) 
     	{
     		int i = pos;		/* i用于主串S中当前位置下标值,若pos不为1,则从pos位置开始匹配 */
     		int j = 1;			/* j用于子串T中当前位置下标值 */
     		int next[255];		/* 定义一next数组 */
     		get_next(T, next);	/* 对串T作分析,得到next数组 */
     		while (i <= S[0] && j <= T[0]) /* 若i小于S的长度并且j小于T的长度时,循环继续 */
     		{
     			if (j==0 || S[i] == T[j]) 	/* 两字母相等则继续,与朴素算法增加了j=0判断 */
     	      	{
     	         	++i;
     	         	++j; 
     	      	} 
     	      	else 			/* 指针后退重新开始匹配 */
     	      	 	j = next[j];/* j退回合适的位置,i值不变 */
     		}
     		if (j > T[0]) 
     			return i-T[0];
     		else 
     			return 0;
     	}
    
    1. 改进:将get_next(T,next)改为get_nextval(T,next)

       /* 求模式串T的next函数修正值并存入数组nextval */
       void get_nextval(String T, int *nextval) 
       {
         	int i,j;
         	i=1;
         	j=0;
         	nextval[1]=0;
         	while (i<T[0])  /* 此处T[0]表示串T的长度 */
        	{
           	if(j==0 || T[i]== T[j]) 	/* T[i]表示后缀的单个字符,T[j]表示前缀的单个字符 */
       		{
             		++i;  
       			++j;  
       			if (T[i]!=T[j])      /* 若当前字符与前缀字符不同 */
       				nextval[i] = j;	/* 则当前的j为nextval在i位置的值 */
             		else 
       				nextval[i] = nextval[j];	/* 如果与前缀字符相同,则将前缀字符的 */
       											/* nextval值赋值给nextval在i位置的值 */
           	} 
       		else 
       			j= nextval[j];			/* 若字符不相同,则j值回溯 */
         	}
       }
      

下载资源

资源链接

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值