返回

浏览器输入URL发生了什么?

前端

夜深了,静下心来码字。本文主要从两个方面去聊,第一是网络知识(参考小满zs网络课程),第二呢,是leetcode的算法题。小伙伴问了,我™进来看发生了什么的,你跟我聊算法搞毛线?各位老哥们先别急,本文仅以算法题为引,讲述输入网址后网页如何加载的问题。

一、算法题 引入

给你一个字符串s,找出s中最长的回文子串。

毫无疑问,这道题可以使用暴力法解决,暴力法的思路是枚举所有的子串,判断每个子串是否是回文,如果子串回文,则更新最长回文子串长度和子串起始下标和结束下标。

步骤1 枚举起始位置,记为left=0;

步骤2 枚举终止位置,记为right=0;

步骤3 如果left<=right,判断s[left]和s[right]是否相等,相等则判断[left,right]是否是回文,如果是,则判断是否大于最长回文子串长度,如果大于则更新最长回文子串长度和子串起始下标和结束下标;

步骤4 如果s[left]和s[right]不相等,说明[left,right]区间不包含回文子串,则left=left+1, right=right-1, 进入**步骤3** 继续判断。

步骤5 当left>right时,终止枚举。

这样来看,暴力法的复杂度为O(n^2)。

很明显,这种方法在实际应用中效率太低,面对长度超长或者无限长的字符串,那是根本无法完成的。

于是,人们提出了马拉车算法,该算法可以在O(n)的时间复杂度内求解字符串中最长回文子串。

此处仅作简单原理介绍,不做详细赘述。

马拉车算法原理

步骤1 将字符串s预处理,在s的头部和尾部各添加一个特殊字符,记为'$'。

步骤2 初始化一个数组P,P[i]表示以第i个字符为中心的最长回文子串长度。

步骤3 初始化一个变量C,表示回文中心,初始化一个变量R,表示回文的右边界。

步骤4 遍历字符串s,对于每个字符s[i]:

* 如果i>R,则C=i, R=i;
* 否则,找到一个变量j,使得i关于C是对称的,即i-C=C-j;
* 如果i+P[j]<=R,则P[i]=P[j];
* 否则,令i关于C的对称点k=R-(i-C),如果s[k]=s[i],则P[i]=P[k]+1,否则P[i]=1;
* 如果i+P[i]>R,则C=i, R=i+P[i];

步骤5 最长回文子串长度为max(P)。

上面说算法优化了,但实际应用呢?

二、算法与网络知识结合

网络编程相关的算法题,多半会涉及到数据结构的设计,例如链表,哈希表等,这些数据结构可以在很多问题中体现出来,这里我们只讲最长回文子串和算法题有什么关系。

在讲解最长回文子串之前,先科普一下浏览器是怎么处理输入的url的。

步骤1 当您在浏览器中输入一个URL时,浏览器首先会检查您输入的URL是否包含协议。如果包含协议,则浏览器会直接将URL发送给相应的协议处理程序。例如,如果URL包含“http://”或“https://”,则浏览器会将URL发送给HTTP或HTTPS协议处理程序。

步骤2 如果您输入的URL不包含协议,则浏览器会将URL发送给默认的协议处理程序。默认的协议处理程序通常是HTTP协议处理程序。

步骤3 协议处理程序收到URL后,会将URL解析成一个域名和一个端口号。

步骤4 协议处理程序会向域名对应的IP地址发送一个DNS查询请求。DNS服务器会将域名解析成一个IP地址。

步骤5 协议处理程序收到IP地址后,会向IP地址对应的服务器发送一个HTTP请求。

步骤6 服务器收到HTTP请求后,会处理请求并返回一个HTTP响应。

步骤7 浏览器收到HTTP响应后,会将响应的内容渲染成网页。

三、如何设计数据结构

看到这里,有人要问,网络相关知识,你说半天和你的回文子串算法题有什么关系?

关系大了,当你得知了浏览器处理URL的步骤后,你会发现,有必要用一个数据结构记录URL的解析过程,设计一个合理的并且可以控制数据结构复杂度上限的数据结构,你才能称的上一个合格的网络工程师。

数组?不行,因为数组的复杂度是固定的。链表?不行,链表的复杂度太高。

嗯,哈希表倒是不错,哈希表的复杂度为O(1)。

我们把域名当作key,IP地址当作value,构建哈希表,这样,无论是请求还是响应,我们可以通过哈希表的key值快速地找到对应的value值,这样既降低了网络请求的时间复杂度,又可以提高代码的响应效率。

四、总结

希望各位小伙伴通过阅读本文,对最长回文子串的算法有了更深的理解,也对网络编程相关算法题有了新的认识。

加油!小伙伴们!