KMP

1:简单的模式匹配算法(朴素的模式匹配算法)

该算法由于要回退,所以算法的时间复杂度为最坏的情况下On * m,nm分别为主串和模式串的长度

code:

//返回t子串在ch[i....n]主串中的位置,位置从零开始,如果不存在,返回-1
int indexOf (char *ch,char *t,int i) {
	int lenCh = strlen (ch);
	int lenT = strlen (t);
	int j = 0;
	while (i < lenCh && j < lenT) {
		if (ch[i] == t[j]) {
			i++;
			j++;
		}else {
			//回退
			i = i - j + 1;
			j = 0;
		}
	}
	if (j >= lenT) {
		return i - lenT;
	}else {
		return -1;
	}
}


总结:

虽然时间复杂度为On*m,但是在一般的情况下,其中实际的执行时间近似于O(n+m),所以至今仍然很多地方在使用。记得以前用过java Strring类的indexOf这个函数,于是看了一下String类的indexOf(String target,int fromIndex)的实现,使用的就是该简单算法。


2

由于有了回退,就导致了简单模式匹配的算法时间最坏的情况下时间复杂度为O(n*m),,那么有没有一种可能,当出现主串中的S[i]字符和模式串中T[j]不匹配时,下标i不需要回退,

而是将模式尽可能的向右滑动,让S[i]T[k]再进行比较,即是:当主串中下标为i的字符与模式串中下标为j的字符失配时,主串中的下标为i的字符应该和模式串中的哪个字符进行比较。

主串为s[0]s[1]s[2]s[3].....s[n],模式串为t[0]t[1]t[2]t[3].....t[m]

假设在某次失配的时候主串中下标为i的字符和模式串中下标为k的字符比较,则有:

“t[0]t[1]t[2]t[3]....t[k-1]” = = “s[i-k]s[i-k+1]s[i-k+2]...s[i-1]”,  (1)

从已经得到部分匹配,则有:

t[j-k]t[j-k+1]t[j-k+2].....t[j-1]”== “s[i-k]s[i-k+1]s[i-k+2]...s[i-1]” , (2)

综合(1)和(2)得出:

“t[0]t[1]t[2].....t[k-1]” == “t[j-k]t[j-k+1]t[j-k+2].....t[j-1]”(3

 前者可以看成是部分匹配的前缀,后者可以看成是部分匹配的后缀。

即前缀等于后缀,这里还不可以得到是最大前缀应该等于最大后缀。

看一个具体的例子:

s[0],s[1],s[2]......s[i-j],s[i-j+1]....s[i-1],s[i],s[i+1]...s[n]

                           t[0],t[1]...........t[j-1],t[j],t[j+1].....t[m]

假设主串和模式串在s[i]t[j]处失配。

(1):t[0]向后移动一位

s[0],s[1],s[2]......s[i-j],s[i-j+1],s[i-j+2]....s[i-1],s[i],s[i+1]...s[n]

                                     t[0],   t[1].................. t[j-1],t[j],t[j+1].....t[m] 

如果s[i-j+1] = t[0],s[i-j+2] = t[1]...s[i] = t[j-1](很显然是最大前缀和后缀),则主串中的s[i]在和t[j]失配的情况下,s[i]应该和t[j-1]再进行比较。否则,即s[i-j+1] = t[0],s[i-j+2] = t[1]...s[i] = t[j-1]其中至少有一个不等,此时,主串和模式串就没有比较必要,继续执行(1),知道找到一个最大前缀等于后缀或者不存在这样的前缀和后缀停止。

用一个next[j]来表示模式串在下标j处和主串在下标i处失配,主串s[i] 应该和模式串中的哪个位置的字符比较。很显然next[]数组的求值与主串是无关的。

下面求解next数组:

已知:next[j] = k;其中0<=k < j-1

(1):当:t[k] == t[j],next[j+1] = next[j] + 1

(2)当:t[k] != t[j],此时模式串即是模式串也是主串,k位置失配,k’ = next[k],

   如果:t[j] == t[k’],则next[j+1] = k’ + 1next[j+1] = next[k] + 1;

   如果t[j] != t[k’],重复进行(2)过程,直到找到一个 _k值,使得t[_k] == t[j]或者t[j] = 0;

根据上面的想法具体的代码如下:


#define MAX_LENGTH  20
int next[MAX_LENGTH];
/**求next函数的算法*/
void getNext (char * ch) {
		int i = 0,j = -1;
		int length = strlen (ch);
		next[0] = -1;//下标从零开始
		while (i < length-1) {
			if (j == -1 || ch[i] == ch[j]) {
				++i; 
				++j;
				next[i] = j;
			}else {
				j = next[j];	
			}
		}
}



int indexOf (char * s,char * t,int fromIndex) {
	int i,j;
	int sLen = strlen (s);
	int tLen = strlen (t);
	getNext (t);
	i = fromIndex;
	j = 0;
	while (i < sLen && j < tLen) {
		if (j == -1 || s[i] == t[j]) {
			++i;
			++j;
		}else {
			j = next[j];
		}
	}
	if (j >= tLen) {
		return i - tLen;
	}else {
		return -1;
	}
}
int main () {
	char *ch = "abxye";
	char *ch2 = "xy";
	int position = indexOf (ch,ch2,1);
	printf ("%d\n",position);
	return 0;
}

Example:

  i 

S:a b a b a b c

T:a b a b c 

  j

1:首先有next[0] = -1;

2:i = 0,j = -1; 因为j == -1,所以有:i = i + 1 = 1,j = j + 1 = 0 ,next[1] = 0;

3:i = 1,j = 0;因为t[i] = t[1] = b,t[j] = t[0] = a, a != b所以:j = next[j] = next[0] = -1

4:i = 1,j=-1;因为j == -1,所以:i = i + 1 = 2, j = -1 + 1 = 0 ,next[2] = 0;

5:i = 2,j = 0;因为t[2] = t[0] = a,所以:i = 2 + 1 = 3,j = 0 + 1 = 1,next[3] = j = 1;

6:i = 3,j = 1;因为t[3] =t[1] = b,所以:i = 3 + 1 = 4,j = 1 + 1 = 2;,next[4] = 2;

改进后的next函数如下:
void get_nextval(char const* ptrn, int plen, int* nextval)    
{    
    int i = 0;     
    nextval[i] = -1;    
    int j = -1;    
    while( i < plen-1 )    
    {    
        if( j == -1 || ptrn[i] == ptrn[j] )   //循环的if部分     
        {    
            ++i;    
            ++j;    
            //修正的地方就发生下面这4行     
            if( ptrn[i] != ptrn[j] ) //++i,++j之后,再次判断ptrn[i]与ptrn[j]的关系     
                nextval[i] = j;      //之前的错误解法就在于整个判断只有这一句。     
            else    
                nextval[i] = nextval[j];    
        }    
        else                                 //循环的else部分     
            j = nextval[j];    
    }    


内容概要:本书《Deep Reinforcement Learning with Guaranteed Performance》探讨了基于李雅普诺夫方法的深度强化学习及其在非线性系统最优控制中的应用。书中提出了一种近似最优自适应控制方法,结合泰勒展开、神经网络、估计器设计及滑模控制思想,解决了不同场景下的跟踪控制问题。该方法不仅保证了性能指标的渐近收敛,还确保了跟踪误差的渐近收敛至零。此外,书中还涉及了执行器饱和、冗余解析等问题,并提出了新的冗余解析方法,验证了所提方法的有效性和优越性。 适合人群:研究生及以上学历的研究人员,特别是从事自适应/最优控制、机器人学和动态神经网络领域的学术界和工业界研究人员。 使用场景及目标:①研究非线性系统的最优控制问题,特别是在存在输入约束和系统动力学的情况下;②解决带有参数不确定性的线性和非线性系统的跟踪控制问题;③探索基于李雅普诺夫方法的深度强化学习在非线性系统控制中的应用;④设计和验证针对冗余机械臂的新型冗余解析方法。 其他说明:本书分为七章,每章内容相对独立,便于读者理解。书中不仅提供了理论分析,还通过实际应用(如欠驱动船舶、冗余机械臂)验证了所提方法的有效性。此外,作者鼓励读者通过仿真和实验进一步验证书中提出的理论和技术。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值