栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Python

数据结构(四)数组和字符串

Python 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

数据结构(四)数组和字符串

这章就更水了,前半章是我心中的复习快乐章,kmp有点死亡。

1 数组寻址

定义a[9][8][7],a[1][2][3]是数组中第几个元素
这个从python的角度更好理解一些,三维数组的python输出结果是(可能不标准)

[
 [ 0 1 2 3
   4 5 6 7
   8 9 0 1]
 [ 0 1 2 3
   4 5 6 7
   8 9 0 1]
 [ 0 1 2 3
   4 5 6 7
   8 9 0 1]
]

就是说,三维只不过是把多个二维堆起来,所以
&a[1][2][3] = &a[0][0][0] + sizeof(type) * 1 * 8 * 7 + 2 * 7 + 3

2 矩阵 2.1 特殊矩阵压缩

对角矩阵:就存主对角线上的一维数组即可。

三角矩阵:把上三角/下三角按行撕成一维数组即可。

对称矩阵:当成上三角存。

2.2 稀疏矩阵与三元组表

是指当一个矩阵非常大,但是只有个别的元素是非0元素,就可以只存非0元素即可,也分数组和链表两种方式。

三元组表:每一个里存该非0元素的,行、列、值。按行优先存储。

对于转置矩阵来说,三元组表非常有效,但是如果需要对某一列进行全部元素的操作(例:对第二列的所有元素+5),用三元组表需要遍历整个表格,则需要用十字链表。

十字链表:每个行和列有一个行的头和列的头,然后每一行、每一列都分别是一个循环链表,如书上P52图,这样对一行/一列操作就通过表头遍历循环链表即可。

2.3 字符串

kmp前的都自己看吧,很简单。

重点:不要去网上随便扒kmp的教程,因为不同的教程失败函数的结果可能不一样,如果期末考填空题,用其他教程得到的结果可能会错误。多看看书上这种吧,书上这种失败函数是最不好理解的失败函数方式。下面相应的算法也是随着失败函数的定义方式改变的。

2.3.1 失败函数
void fail(string s) {

    int len=s.length();
    int i=0;
    Next[0]=-1;
    
   	//假设当前的字母为m,上一个字母为n
   	
    for(int j=1;j=0) i=Next[i];	//不断Next找上一个n的后一个是不是m
        
        //下面这个if&else是经典的,判断上一个while循环是通过何种方式结束
        
        if(s[j]==s[i+1]) Next[j]=i+1;	//如果是,那就对上了
        
        else Next[j]=-1;				//一直都对不上,那就是新的
        
    }
}

这个肯定还是不能让你完全明白,那么我现在要举栗子了
(是一个字符串,空格是方便观看)

  1. abcf abcf abcf 的失败函数是:
    -1 -1 -1 -1 0 1 2 3 4 5 6 7
    这个不用特意去通过代码理解,主要是明白失败函数的简单运行方式,但是这样往往会导致错误的理解:就是从头开始比较连续的第几个和当前元素一样且数字连续。

  2. abcf abcd abcf 的失败函数是
    -1 -1 -1 -1 0 1 2 -1 0 1 2 3
    我们可以从这里看到,当字符匹配不上的时候就为-1,但是这里数字也是连续的,即从-1开始的每次+1的递增序列。

  3. abcf abcd abcf abcf 当判断最后一个f时,此时前面的失败函数是这样:
    -1 -1 -1 -1 0 1 2 -1 0 1 2 3 4 5 6
    当我们开始读取最后一个字符’f’时,如何判断它的失败函数呢?为了方便观看,我把代码贴到下面。这里我们发现最后一个数字是3,跟前面就不是连续的了,看起来的规律不一定准确,千万要用代码实现一遍。

        i=Next[j-1];
		// i=Next[14] = 6      首先找f字母的上一个字母c,c的Next是6
		
        while(s[j]!=s[i+1]&&i>=0) i=Next[i];
		// s[15]=f ≠ s[7]=d    i=Next[6] = 2
		// s[15]=f =s[3]=f     跳出循环
		
		//值得注意的是,如果最开始加一句i=j-1=14,将第一句改成第一次i=Next[i]
		//在这里最开始i曾被赋值为14,6,2,且这三个位置上的字母都是c
		//且Next[14]=6,Next[6]=2,就是分别用7和3与15比较是否相同

        if(s[j]==s[i+1]) Next[j]=i+1;	
        //因为是通过s[j]==s[i+1]跳出while,所以走这条if,Next[15]=3
2.3.2 KMP算法
int kmp(string s, string p){ 	// s是父串,p是子串
	int len_s = s.length();
	int len_p = p.length();
	int i = 0, j = 0; 			// i是父串的指针,j是子串的指针
	while (i < len_s && j < len_p){
		if (s[i] == p[j]){      // 当前位置匹配成功
			i++;  j++;  		// 指针都向后移动一位
			if(j==len_p) return i-len_p;  //匹配结束,返回匹配位置
		}
		else{
			//子串第一位都匹配失败,找父串下一个字母匹配
			if(j==0) i++; 
			//字串非第一位匹配失败,那找该字母的上一位的Next的下一位
			else j=Next[j-1]+1;
		}
	}
	return -1;
}

对于 abcf abcd abcf abcf 这个字符串,失败函数为
-1 -1 -1 -1 0 1 2 -1 0 1 2 3 4 5 6 3

当前14位都匹配成功,到第15位f匹配失败的时候,那就找第14位的Next,j=Next[14]=6;查询第7位字母为d≠f,会继续匹配失败找j=Next[6]=2;查询第3位字母为f匹配成功,走向i++&j++。

上述过程一共进行三次循环:第一次匹配失败j=Next[14]=6,第二次匹配失败j=Next[6]=2,第三次匹配成功i++&j++。

2.3.3 补充

对于书上这种kmp,我能说的言尽于此,我当时理解的过程也都在这里,如果还是觉得不懂,就多找数据一遍遍手动过代码,就能理解好了。

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/325734.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号