扩展_扩展板 - CSDN
  • Extensions Manager 安装地址: ... 这是一款很方便的扩展应用和主题管理器,它可以快速轻松地启用、禁用、卸载你的扩展应用,显示你正在操作的扩展应用,并且不处理私人信...

    Extensions Manager

    安装地址:

    https://chrome.google.com/webstore/detail/extensions-manager-aka-sw/lpleipinonnoibneeejgjnoeekmbopbc?hl=en

    这是一款很方便的扩展应用和主题管理器,它可以快速轻松地启用、禁用、卸载你的扩展应用,显示你正在操作的扩展应用,并且不处理私人信息和敏感信息,可以让你的浏览器更加清楚有条理。

    HTTPS Everywhere

    安装地址:

    https://chrome.google.com/webstore/detail/https-everywhere/gcbommkclmclpchllfjekcdonpmejbdp?hl=en

    首先来和你简单介绍下什么是HTTPS。

    “HTTPS”是一种网站协议,可以确保网站在你访问之前是安全的。与之对应的是网站的开头为:HTTP

    所以存在两种区别,即 “HTTPS 和 HTTP”

    简单来讲,访问Https的网站其实是更安全的,而http其实更容易遭受攻击,也意味着这样的网站更存在风险,比如说我的博客,大家可以观察一下,我的博客的链接是:

    很多人会问我,为什么我不去做https?

    我的回答是,因为我的博客是免费给大家看,又不交易,又不下单,所以我懒得搞这个https。

    所以看到这里,你就明白了,因为很多互联网的小白,很多时候察觉不出网站是否被钓鱼,自己判别不出来,那么就可以利用HTTPS Everywhere。

    HTTPS Everywhere在许多站点上自动使用HTTPS 安全性,它会将访问网站的请求重写为Chrome版本,这样就可以确保浏览器生成的是该网站的安全版本,保护你免受各种形式的监视和账户劫持、某些形式的审查。

    当我在我的网站上开启https的时候。

     

    你看我的博客就变成了 https了,这样你就可以安全访问了。

    所以你看是不是非常的使用方便呢?

    对了,类似的工具,还有一款叫,J2Team Security 也非常的好用,可以很好的保护你的网站的隐私。

    Click&Clean

    安装地址

    https://chrome.google.com/webstore/detail/clickclean/ghgabhipcejejjmhhchfonmamedcbeod?hl=en

    这款软件是干什么用的呢?

    如果你的工作经常要搜索、下载资料,那你需要这样一款快速清除历史缓存、提高运行速度的应用。

    其实我们也可以直接在浏览器上清空缓存,但是需要点击两个步骤,比较麻烦,但是通过这个插件,直接一键点击,使用起来非常的方便。

    所以只需轻松点击Click&Clean按钮,就可以清除缓存、网址搜索、网站Cookie和下载记录。

    另外这款工具,它还可以扫描计算机中的病毒,并清理硬盘驱动中未使用的应用软件,帮你提升网速。

    Bitly

    安装地址

    https://chrome.google.com/webstore/detail/bitly-unleash-the-power-o/iabeihobmhlgpkcgjiloemdbofjbdcic

    bitly相信很多人都已经用到过!

    就是一款缩短网址,可以把长链接变成短链接,这样你在外面推广的时候,会让人觉得比较清爽,可靠。

    太长的链接,给人的感觉很不专业,又影响了人的点击欲望,因此就会经常用到缩短工具。该用具就是生成短连接的,玩过新浪微博的人都知道!

    BuzzSumo

    安装地址

    https://chrome.google.com/webstore/detail/buzzsumo/gedpbnanjmblcmlfhgfficjnglidndfo

    这个工具让你能够很简单地查看内容的参与度。还可以用它执行竞争对手分析,让你快速的知道,竞争对手有哪些好的文章是被分享的最多的,哪些文章是给他们带去最大的流量。

    那么你就可以模仿他们的文章,知道写什么样的话题,素材最有用,这是一个非常好的对于内容挖掘的好方法

    Pinterest

    安装地址

    https://chrome.google.com/webstore/detail/pinterest-save-button/gpdjojdkbbmdfjfahjcgigfpmkopogic

    这是一款让你无需离开你正在进行的操作,轻松将内容保存到Pinterest板上的一款应用。

    一句话,利用这个工具,可以很快速的把好看的图片Pin到你的board中。

    因此你可以一次性在你的Pinterest板上面保存多个内容。保存的方法是单击每个博客文章或者图像,以便单独地将每个文章分别固定在你的Pinterest板上,这样使用起来非常的方便。

    Instagram for Chrome

    安装地址

    https://chrome.google.com/webstore/detail/instagram-for-chrome/opnbmdkdflhjiclaoiiifmheknpccalb/related

    这个工具是干什么用的呢?

    如果你想要实时看到Instagram上面的消息,又嫌一直查看手机太麻烦的话,就可以使用这个应用,它能让你直接在浏览器上面查看Instagram的消息。

    Checkbot

    安装地址

    https://chrome.google.com/webstore/detail/checkbot-seo-web-speed-se/dagohlmlhagincbfilmkadjgmdnkjinl?hl=en

    Checkbot是一款结合了SEO优化技术和安全性的应用,帮助你分析对于搜索引擎来说网站的优化程度和安全性。

    你看这个很重要吧。

    很多人砸了很多钱在广告上,可是网站都没有优化好,那投的广告的意义在哪里,对不对。

    我们知道,谷歌等搜索引擎除了看排名中的内容质量以外,网站的安全性也是一个重要的指标考核,因此这款应用对于SEO内容负责人和网站开发人员来说是很有用的。

    Checkbot是一个功能强大的网站审核员,可以在几分钟内检查(每个站点)250个以上网址的网速、SEO、整体安全性,发现损坏的链接、重复的标题、无效的HTML/CSS/JavaScript,不安全的密码表单、重定向链、混合内容错误等。

    对于网站的排查,非常有效。

    MozBar

    安装地址:

    https://chrome.google.com/webstore/detail/mozbar/eakacpaijcpapndcfffdgphdiccmpknp

    我主要是用这个工具看两点:

    第一:网站的PA和DA值

    第二:网页的质量得分

    Check My Links

    安装地址:

    https://chrome.google.com/webstore/detail/check-my-links/ojkcdipcgfaekbeaelaapakgnjflfglf

    这款应用可以快速扫描网页,显示出哪些链接可以正常工作,哪些链接已经打不开。

    其实呢,可以利用这个工具找404的文章,来做外链,那么这个工具必将会派上用场。

    NoFollow

    安装地址: https://chrome.google.com/webstore/detail/nofollow/dfogidghaigoomjdeacndafapdijmiid/related

    句话,利用这个工具可以快速的查看哪些链接是被索引的,哪些链接是不被索引的。

    如果这个工具检测出来,如上图(红色方框)则代表这个链接其实是不被索引的,不被索引的链接,当然也就是不被传递网站的权重。

    “那啥,啥叫权重啊,啥叫索引啊?

    科普科普

    权重怎么说呢,就是一个网站的综合性指标,就好比,我们经常说一个人一样,我们说他的威望很高。

    你的威望越高,就代表你说话越有份量!

    权重和这个威望其实有点相似,一个网站的权重越高,就越代表他的综合排名啊,网站的各项指标都很好,那么搜索引擎对这样的网站是有加权的。

    所以如果你找一个有权重的网站做推广,可是发现对方设置了nofollow,那对不起,这代表,这个链接是不被Google索引的,也就代表对方的网站是不传递权重的。

    所以做SEO的人可以使用这个扩展来确定外部网站是否通过跟踪的链接或者是索引链接做了外链。

    此外,你还可以在不想被抓取的网页上使用Nofollow链接,例如登陆页面或是感谢页面,使用这个应用可以帮助你轻松仔细地检查编码链接是否正确。如上图Nofollow链接用红框标记出来了。

    OneTab

    安装地址

    https://chrome.google.com/webstore/detail/onetab/chphlpgkkbolifaimnlloiipkdnihall

    我们经常会发现,有时候你的浏览器会不自觉的多开了很多窗口,而一旦你同时开了很多窗口,那么你的电脑运行速度其实会变慢的。

    那么这个工具就可以派上用场了。

    你可以单击OneTab图标,将所有标签页转换成一个列表。当你需要再次访问这些标签时,可以单独或全部恢复它们。

    通过这个方法,它能减少谷歌浏览器打开的标签页的数量,这样可以大大节省高达95%的内存!

    AwesomeScreenshot

    安装地址:

    https://chrome.google.com/webstore/detail/awesome-screenshot-screen/nlipoenfbbikpbjkfpfillcgkoblgpmj

    这款工具很简单,就是一个截图工具。

    和我们经常用到的QQ截图啊,微信截图啊,其实是差不多的。

    只是有时候我没有登录qq或者微信,我就可以直接用工具了。

    另外这个屏幕截图扩展工具,还有注释和照片编辑功能,并能保留在浏览器中。

    在截取屏幕选定区域或整个网页的屏幕截图后,还有裁剪、突出显示、绘制形状以及马赛克等功能。

    功能还是很多的!

    Evernote Web Clipper

    安装地址:

    https://chrome.google.com/webstore/detail/evernote-web-clipper/pioclpoplcdbaefihamjohnefbikjilc

    我相信,凡是使用过印象笔记的,应该会对这个裁剪工具会非常熟悉吧

    通过Evernote Web Clipper这个裁剪工具,比如说,你看到一篇非常好的文章,那么你可以不用手动copy复制,因为这样非常的麻烦,你只要一键点击裁剪按钮,然后整篇文章就会被保存在你印象笔记中的账户中。

    这样今后你可以对保存下来的文章,反复的阅读。

    允许我再次强调下,文章的归纳是非常重要的,有太多的人,做的笔记都非常乱,我建议大家还是多花点时间学学,怎么做笔记。

    不要觉得这些很简单,当你知道如何高效的运用笔记,他所给你带来的价值将是巨大的。

    Evernote Web Clipper,这个功能我经常使用,太方便了,强烈推荐!

    Grammarly

    安装地址:

    https://chrome.google.com/webstore/detail/grammarly-for-chrome/kbfnbcaeplbcioakkpcpgfkobkghlhen?hl=en

    这款工具是用于审查在你博客写完英文文章,或者邮件的时候,利用这个工具可以很好的检查你文章的拼写、语法和单词使用是否正确。

    像我们团队中的内容编辑部门和产品运营部门,基本每天都会用到这个工具!

    一把好的剑,只有被懂得人所掌握,才能发挥出他真正的价值,反之,再好的剑,都是一把废铁。

    对于工具来说,显然这个道理同样适用!

    展开全文
  • 扩展KMP的详细理解

    2018-05-22 16:37:02
    扩展KMP的详细理解扩展KMP求的是对于原串S1的每一个后缀子串与模式串S2的最长公共前缀。它有一个next[]数组和一个extend[]数组。next[i]表示为模式串S2中以i为起点的后缀字符串和模式串S2的最长公共前缀长度.其中,...

    扩展KMP的详细理解

    扩展KMP求的是对于原串S1的每一个后缀子串与模式串S2的最长公共前缀。它有一个next[]数组和一个extend[]数组。

    next[i]表示为模式串S2中以i为起点的后缀字符串和模式串S2的最长公共前缀长度.

    其中,next[0]=l2;

    next[i]=max{ k|i<=i+k-1<l2 &&S2.substring(i,i+k-1) == S2.substring(0,k-1) }

    其中str.substring(i, j)表示str从位置i到位置j的子串,如果i>j则,substring为空。

    extend[i]表示为以字符串S1中以i为起点的后缀字符串和模式串S2的最长公共前缀长度.

    下面我们先以一组样例来理解扩展KMP的过程


    (1) 第一步,我们先对原串S1和模式串S2进行逐一匹配,直到发生不配对的情况。我们可以看到,S1[0]=S2[0],S1[1]=S2[1],S1[2]=S2[2],S1[3] ≠S2[3],此时匹配失败,第一步结束,我们得到S1[0,2]=S2[0,2],即extend[0]=3;

    (2) Extend[0]的计算如第一步所示,那么extend[1]的计算是否也要从原串S1的1位置,模式串的0位置开始进行逐一匹配呢?扩展KMP优化的便是这个过程。从extend[0]=3的结果中,我们可以知道,S1[0,2]=S2[0,2],那么S1[1.2]=S2[1,2]。因为next[1]=4,所以S2[1,4]=S2[0,3],即S2[1,2]=S[0,1],可以得出S1[1,2]=S2[1,2]=S2[0,1],然后我们继续匹配,S1[3] ≠S2[3],匹配失败,extend[1]=2;

    (3) 因为extend[1]=2,则S1[1,2]=S2[0,1],所以S1[2,2]=S2[0,0],因为next[0]=5,所以S1[0,5]=S2[0,5],所以S2[0,0]=S2[0,0],又回到S1[2,2]=S2[0,0],继续匹配下一位,因为S1[3] ≠S2[1],所以下一位匹配失败,extend[2]=1;

    (4) 到计算原串S1的3号位置(在之前的步骤中能匹配到的最远的位置+1,即发生匹配失败的位置),这种情况下,我们会回到步骤(1)的方式,从原串S1的3号位置开始和模式串的0号位置开始,进行逐一匹配,直到匹配失败,此时的extend[]值即为它的匹配长度。因为S1[3] ≠S2[0],匹配失败,匹配长度为0,即extend[3]=0;

    (5) 计算S1的4号位置extend[]。由于原串S1的4号位置也是未匹配过的,我们也是回到步骤(1)的方式,从原串S1的4号位置开始和模式串S2的0号位置开始进行逐一匹配,可以看到,S1[4]=S2[0],S1[5]=S2[1],S1[6]=S2[2],S1[7]=S2[3],S1[8]=S2[4],S1[9] ≠S2[5],此时原串S1的9号位置发生匹配失败,最多能匹配到原串S1的8号位置,即S1[4,8]=S2[0,4],匹配长度为5,即extend[4]=5;

    (6) 计算S1的5号位置extend[].由于原串S1的5号位置是匹配过的(在步骤(5)中匹配了),我们从extend[4]=5得出,S1[4,8]=S2[0,4],即S1[5,8]=S2[1,4],和步骤(2)的计算方式类似,我们从next[1]=4可知,S2[0,3]=S2[1,4],即S1[5,8]=S2[0,3],然后我们继续匹配原串S1的9号位置和S2的4号位置,S1[9]=S2[4],继续匹配,S1[10]=S2[5],此时原串S1的所有字符皆匹配完毕,皆大欢喜,则S1[5,10]=S2[0,5],extend[5]=6;

    (7) 从原串S1的6号位置到10号位置的extend[]的计算,与原串S1的1号位置到3号位置的计算基本相同。S1[6,10]=S2[1,5],因为next[1]=4,所以S2[1,4]=S[0,3],所以S1[6,9]=S2[0,3],此时不在需要判断匹配下一位的字符了,直接extend[6]=4;(具体原因在后面的分析总结中有说明)

    (8) S1[7,10]=S2[2,5],因为next[3]=2,所以S2[3,4]=S2[0,1],所以S1[8,9]=S2[0,1],匹配长度为2,即extend[7]=3;

    (9) S1[8,10]=S2[3,5],因为next[3]=2,所以S2[3,4]=S2[0,1],所以S1[8,9]=S2[0,1],匹配长度为2,即extend[8]=2;

    (10) S1[9,10]=S2[4,5],因为next[4]=1,所以S2[4,5]=S2[0,0],所以S1[9,9]=S2[0,0],匹配长度为1,即extend[9]=1;

    (11) S1[10,10]=S2[5,5],因为next[5]=0,所以匹配长度为0,即extend[10]=0;

    至此,所有的匹配已经结束,相信,如果你仔细的看了上述的例子,已经对扩展KMP有了一定的了解了,它的计算过程中,主要是步骤一和步骤二的计算过程。下面我们对这两个过程归纳一下:

     

    我们先定义,从0~k的计算过程中,我们已经计算出它们的extend[]值了和在匹配的过程中从Po开始匹配能匹配到的最远位置P,即Po+extend[Po]-1=P;

    步骤一:当前需要计算的extend[k+1],原串S1中k+1号位置还未进行过匹配,则从原串S1的k+1号位置和模式串S2的0号位置开始进行逐一匹配,直到匹配失败,则extend[k+1]=匹配长度,此外,还要相应的更新Po值和最远匹配位置P.

    步骤二:当前需要计算的extend[k+1],原串S1中k+1号位置已经进行过匹配。首先,我们从Po+extend[Po]-1=P中,可以得知S1[Po,P]=S2[0,P-Po],所以S1[k+1,P]=S2[k+1-Po,P-Po],令len=next[k+1-Po]

    (1) 当(k+1)+len-1=k+len<P时,即一下情况:

     

    我们可以得出,len=next[k+1-Po],S2[0,len-1]=S2[k+1-Po,k+Po+len],所以S1[k+1,k+len]=S2[k+1-Po,k+Po+len]=S2[0,len-1],即extend[k+1]=len;

    那么会不会出现S1[k+len+1]=S2[len]的情况呢?答案是否定的

    假如S1[k+len+1]=S2[len],则S1[k+1,k+len+1]=S2[0,len]

    因为k+len<P,所以k+len+1<=P

    所以S1[k+1,k+len+1]=S2[k+1-Po,k+Po+len+1]=S2[0,len]

    此时,next[k+1-Po]=len+1与原假设不符合,所以此时S1[k+len+1]≠S2[len],不需要再次判断。

    (2)当(k+1)+len-1=k+len>=P时,即一下情况:

     

    我们可以看出,由S1[Po,P]=S2[0,P-Po]可得出S1[k+1,P]=S2[k+1-Po,P-po],len=next[k+1-Po],所以S2[0,len-1]=S2[k+1-Po,k+len+Po]

    所以S1[k+1,p]=S2[0,P-k-1]

    由于大于P的位置我们还未进行匹配,所以从原串S1的P+1位置开始和模式串的P-k位置开始进行逐一匹配,直到匹配失败,并更新相应的Po位置和最远匹配位置P,此时extend[k+1]=P-k+后来逐一匹配的匹配长度。

    其实,next[]数组的计算过程与extend[]的计算过程基本一致,可以看成是原串S2和模式串S2的扩展KMP进行计算,每次计算extend[k+1]时,next[i](0<=i<=k)已经算出来了,算出extend[k+1]的时候,意味着next[k+1]=extend[k+1]也计算出来了。

    时间复杂度分析

    通过上面的算法可知,我们原串S1的每一个字符串只会进行一次匹配,extend[k+1]的计算可以通过之前extend[i](0<=i<=k)的值得出,由于需要用相同的方法对模式串S2进行一次预处理,所以扩展KMP的时间复杂度为O(l1+l2),其中,l1为原串S1的长度,l2为模式串S2的长度。

    HDU - 2328 

    Corporate Identity

    题意:给你n个字符串,求这n个字符串的最长公共子串
    思路:有多种方面可以做出这道题,我们这里先找出最短的一个母串,然后枚举它的每一个子串,对于每一个子串和原来的母串进行扩展KMP匹配,然后记录匹配的最大值和对应的位置即可,需要注意的时,多个答案时,输出字典序最小的子串。
    //#include<bits/stdc++.h>
    /*
    next[0]=l2; 
    next[i]=max{ k|i<=i+k-1<l2 &&str.substring(i,i+k-1) == str.substring(0,k-1) } 其中str.substring(i, j)表示str从位置i到位置j的子串,如果i>j则,substring为空。
    next[i]表示为以模式串s2中以i为起点的后缀字符串和模式串s2的最长公共前缀长度.
    extend[i]表示为以字串s1中以i为起点的后缀字符串和模式串s2的最长公共前缀长度.
    */
    #include<iostream>
    #include<algorithm>
    #include<cstring>
    #include<string>
    #include<map>
    using namespace std;
    const int maxn=100010;   //字符串长度最大值
    const int INF=int(1e9);
    int nxt[maxn],ex[maxn]; //ex数组即为extend数组
    char s1[maxn],s2[maxn];
    char s[5010][210];
    //预处理计算next数组
    void get_next(char *str) {
    	int i=0,j,po,len=strlen(str);
    	nxt[0]=len;//初始化next[0]
    	while(str[i]==str[i+1]&&i+1<len)//计算next[1]
    		i++;
    	nxt[1]=i;
    	po=1;//初始化po的位置
    	for(i=2; i<len; i++) {
    		if(nxt[i-po]+i<nxt[po]+po)//第一种情况,可以直接得到next[i]的值
    			nxt[i]=nxt[i-po];
    		else { //第二种情况,要继续匹配才能得到next[i]的值
    			j=nxt[po]+po-i;
    			if(j<0)j=0;//如果i>po+next[po],则要从头开始匹配
    			while(i+j<len&&str[j]==str[j+i])//计算next[i]
    				j++;
    			nxt[i]=j;
    			po=i;//更新po的位置
    		}
    	}
    }
    //计算extend数组
    bool exkmp(char *s1,char *s2) {
    	int i=0,j,po,len=strlen(s1),l2=strlen(s2);
    	get_next(s2);//计算子串的next数组
    	while(s1[i]==s2[i]&&i<l2&&i<len)//计算ex[0]
    		i++;
    	ex[0]=i;
    	po=0;//初始化po的位置
    	if(ex[0]==l2)
    		return true;
    	for(i=1; i<len; i++) {
    		if(nxt[i-po]+i<ex[po]+po)//第一种情况,直接可以得到ex[i]的值
    			ex[i]=nxt[i-po];
    		else { //第二种情况,要继续匹配才能得到ex[i]的值
    			j=ex[po]+po-i;
    			if(j<0)j=0;//如果i>ex[po]+po则要从头开始匹配
    			while(i+j<len&&j<l2&&s1[j+i]==s2[j])//计算ex[i]
    				j++;
    			ex[i]=j;
    			po=i;//更新po的位置
    		}
    		if(ex[i]==l2)
    			return true;
    	}
    	return false;
    }
    void char_(char *str1,char *str,int l,int r) {    //将str字符串的(l,r)赋值给str1 
    	for(int i=l; i<=r; i++) {
    		str1[i-l]=str[i];
    	}
    	str1[r-l+1]='\0';
    	return ;
    }
    int main() {
    	int n;
    	while(~scanf("%d",&n)&&n) {
    		scanf("%d",&n);
    		int Min=INF,pos;
    		for(int i=1; i<=n; i++) {
    			scanf("%s",s[i]);
    			if(strlen(s[i])<Min) {    //找出最短母串 
    				Min=strlen(s[i]);
    				pos=i;
    			}
    		}
    		int Max=0;
    		int l=strlen(s[pos]);
    		int left,right;
    		for(int i=0; i<l; i++) {   //枚举母串的每一个子串 
    			for(int j=i; j<l; j++) {
    				if((j-i+1)<Max) continue;   //剪枝 
    				char_(s1,s[pos],i,j);
    				int flag=true;
    				for(int z=1; z<=n; z++) {  //每一个子串和原来的母串进行匹配 
    					if(z==pos) continue;
    					if(exkmp(s[z],s1))
    						continue;
    					flag=false;
    					break;
    				}
    				if(flag) {
    					if(j-i+1==Max){      //记录所有母串的最长公共子串,长度相同的情况下记录字典序最小的子串 
    						for(int z=0;z+left<=right;z++){
    							if(s[pos][z+left]<s[pos][z+i])
    							break;
    							else{
    								if(s[pos][z+left]>s[pos][z+i]){
    									left=i;
    									right=j;
    									break;
    								}
    							}
    						}
    					}
    					if(j-i+1>Max) {
    						left=i;
    						right=j;
    						Max=max(Max,j-i+1);
    					}
    				}
    			}
    		}
    		if(Max==0)
    			printf("IDENTITY LOST\n");
    		else {
    			for(int i=left; i<=right; i++) {
    				printf("%c",s[pos][i]);
    			}
    			printf("\n");
    		}
    	}
    	return 0;
    }

     

    展开全文
  • 为了介绍扩展欧几里得,我们先介绍一下贝祖定理: 即如果a、b是整数,那么一定存在整数x、y使得ax+by=gcd(a,b)。 换句话说,如果ax+by=m有解,那么m一定是gcd(a,b)的若干倍。(可以来判断一个这样的式子有没有解...

    为了介绍扩展欧几里得,我们先介绍一下贝祖定理

               即如果a、b是整数,那么一定存在整数x、y使得ax+by=gcd(a,b)。

    换句话说,如果ax+by=m有解,那么m一定是gcd(a,b)的若干倍。(可以来判断一个这样的式子有没有解)

    有一个直接的应用就是 如果ax+by=1有解,那么gcd(a,b)=1;

    要求出这个最大公因数gcd(a,b),我们最容易想到的就是古老悠久而又相当强大的辗转相除法:

    int gcd(int a,int b)
    {
        return b==0?a:gcd(b,a%b);
    }

    但是,对于上面的式子ax+by=m来说,我们并不仅仅想要知道有没有解,而是想要知道在有解的情况下这个解到底是多少。

    所以,扩展欧几里得

            当到达递归边界的时候,b==0,a=gcd(a,b) 这时可以观察出来这个式子的一个解:a*1+b*0=gcd(a,b),x=1,y=0,注意这时的a和b已经不是最开始的那个a和b了,所以我们如果想要求出解x和y,就要回到最开始的模样。

            初步想法:由于是递归的算法,如果我们知道了这一层和上一层的关系,一层一层推下去,就可以推到最开始的。类似数学上的数学归纳法。

            假设当前我们在求的时a和b的最大公约数,而我们已经求出了下一个状态:b和a%b的最大公因数,并且求出了一组x1和y1使得                          b*x1+(a%b)*y1=gcd

    (注意在递归算法中,永远都是先得到下面一个状态的值)

    这时我们可以试着去寻找这两个相邻状态的关系:

    首先我们知道:a%b=a-(a/b)*b;带入:

    b*x1 + (a-(a/b)*b)*y1

    = b*x1 + a*y1 – (a/b)*b*y1

    = a*y1 + b*(x1 – a/b*y1) = gcd   发现 x = y1 , y = x1 – a/b*y1

    这样我们就得到了每两个相邻状态的x和y的转化,就可以在求gcd的同时对x和y进行求值了hiahia

    --------------------------------------------------------------我是分割线哇---------------------------------------------------------------

    板子板子:

    #include<iostream>
    #include<cstdio>
    #include<cmath>
    
    using namespace std;
    
    int exgcd(int a,int b,int &x,int &y)//扩展欧几里得算法
    {
        if(b==0)
        {
            x=1;y=0;
            return a;  //到达递归边界开始向上一层返回
        }
        int r=exgcd(b,a%b,x,y);
        int temp=y;    //把x y变成上一层的
        y=x-(a/b)*y;
        x=temp;
        return r;     //得到a b的最大公因数
    }

    呼呼

    展开全文
  • VirtualBox 扩展虚拟硬盘容量  最近在虚拟机中下载 Android 源码的过程中,出现了虚拟硬盘不够用的情况。当初安装虚拟机的时候,选择了动态分配存储,想当然的以为硬盘不够用的时候,它会自动扩展,没想到上限是...

        VirtualBox 扩展虚拟硬盘容量

          (转载请标明出处:http://blog.csdn.net/ganshuyu/article/details/17954733    谢谢~ )
           最近在虚拟机中下载 Android 源码的过程中,出现了虚拟硬盘不够用的情况。当初安装虚拟机的时候,选择了动态分配存储,想当然的以为硬盘不够用的时候,它会自动扩展,没想到上限是默认的8G。然后代码下载到一半就悲剧了,于是网搜了一通,把操作过程记录于下,供大伙儿参考:

    预置条件:
    虚拟机:Oracle VM VirtualBox
    OS: Ubuntu 12.10
    虚拟硬盘:动态分配存储

    扩展步骤:
    第一步:修改硬盘镜像文件
    1、虚拟机关机.
    2、确认虚拟机使用文件(后缀为.vdi的文件)路径不带中文字符.
    3、Windows 下按:Windows +R,调出命令行工具,运行命令:
          VBoxManage list hdds    (如果此命令未找到,请将虚拟机安装路径增加至系统环境变量,并重新调出cmd工具.)


        如上图所示,映像的uuid是:a0f06f66-f696-41dc-827a-e79bee50f65b
        然后使用命令:
          VBoxManage modifyhd a0f06f66-f696-41dc-827a-e79bee50f65b   --resize 51200
        操作成功后该虚拟的硬盘即增加了50G,但要注意了,此50G空间还没有分配.

    第二步:分区
        1、虚拟机开机.
        2、查看磁盘情况:
                        $df -ah                  #可以看到磁盘还是7G多,没有增加

              虽然已经扩大了磁盘,但是由于还没有经过分区,指定文件系统[格式化],所以linux操作系统无法识别(其实就相当于你插入了一块新硬盘,但是你并没有对其进行分区、格式化是一个道理)。
       3、开始分区
                         $sudo fdisk /dev/sda

          Disk /dev/sda: 53.7 GB, 53687091200 bytes  #磁盘总量确实增加到了50G
          在Command后输入n(添加新分区),回车:
                  Command action
                          l   logical (5 or over)
                          p   primary partition (1-4)

          从上图可以看到: sda1、sda2、sda5三个分区,而1-4中只用了1和2,所以该步可以选primary partition ,因此输入:p
          剩下步骤全按回车默认,咱们把多出来的空间分成一个分区,然后保存分区信息:
                 Command:w             #保存并退出,分区划分完毕
                 WARNING: Re-reading the partition table failed with error 16: 设备或资源忙.
                 The kernel still uses the old table. The new table will be used at
                  the next reboot or after you run partprobe(8) or kpartx(8)
                  Syncing disks.                                                
              $ partprobe      #我们不想重启系统,可以运行partprobe命令
           于是我们得到一个可用的块设备文件: /dev/sda3

    第三步:格式化并挂载
      1、格式化分区
                 $sudo mkfs -t ext4 /dev/sda3
      2、挂载分区
                 $sudo  mount  /dev/sda3  /home/ganshuyu/workspace
      3、开机自动挂载,则修改/etc/fstab文件,在这个文件里面添加一行:
                /dev/sda3   /home/ganshuyu/workspace    ext4    defaults        0       1

       至此,容量扩展完成。

    展开全文
  • 一、什么是高并发 高并发(High Concurrency)是互联网分布式系统架构设计中必须考虑的因素之一,它通常是指,通过设计保证系统能够同时并行处理很多请求。 高并发相关常用的一些指标有响应时间(Response Time)...

    转自:https://www.jianshu.com/p/be66a52d2b9b

    一、什么是高并发

    高并发(High Concurrency)是互联网分布式系统架构设计中必须考虑的因素之一,它通常是指,通过设计保证系统能够同时并行处理很多请求。

    高并发相关常用的一些指标有响应时间(Response Time),吞吐量(Throughput),每秒查询率QPS(Query Per Second),并发用户数等。

    响应时间:系统对请求做出响应的时间。例如系统处理一个HTTP请求需要200ms,这个200ms就是系统的响应时间。

    吞吐量:单位时间内处理的请求数量。

    QPS:每秒响应请求数。在互联网领域,这个指标和吞吐量区分的没有这么明显。

    并发用户数:同时承载正常使用系统功能的用户数量。例如一个即时通讯系统,同时在线量一定程度上代表了系统的并发用户数。

    二、如何提升系统的并发能力

    互联网分布式架构设计,提高系统并发能力的方式,方法论上主要有两种:垂直扩展(Scale Up)与水平扩展(Scale Out)。

    垂直扩展:提升单机处理能力。垂直扩展的方式又有两种:

    (1)增强单机硬件性能,例如:增加CPU核数如32核,升级更好的网卡如万兆,升级更好的硬盘如SSD,扩充硬盘容量如2T,扩充系统内存如128G;

    (2)提升单机架构性能,例如:使用Cache来减少IO次数,使用异步来增加单服务吞吐量,使用无锁数据结构来减少响应时间;

    在互联网业务发展非常迅猛的早期,如果预算不是问题,强烈建议使用“增强单机硬件性能”的方式提升系统并发能力,因为这个阶段,公司的战略往往是发展业务抢时间,而“增强单机硬件性能”往往是最快的方法。

    不管是提升单机硬件性能,还是提升单机架构性能,都有一个致命的不足:单机性能总是有极限的。所以互联网分布式架构设计高并发终极解决方案还是水平扩展。

    水平扩展:只要增加服务器数量,就能线性扩充系统性能。水平扩展对系统架构设计是有要求的,如何在架构各层进行可水平扩展的设计,以及互联网公司架构各层常见的水平扩展实践,是本文重点讨论的内容。

    三、常见的互联网分层架构

    常见互联网分布式架构如上,分为:

    (1)客户端层:典型调用方是浏览器browser或者手机应用APP

    (2)反向代理层:系统入口,反向代理

    (3)站点应用层:实现核心应用逻辑,返回html或者json

    (4)服务层:如果实现了服务化,就有这一层

    (5)数据-缓存层:缓存加速访问存储

    (6)数据-数据库层:数据库固化数据存储

    整个系统各层次的水平扩展,又分别是如何实施的呢?

    四、分层水平扩展架构实践

    反向代理层的水平扩展

    反向代理层的水平扩展,是通过“DNS轮询”实现的:dns-server对于一个域名配置了多个解析ip,每次DNS解析请求来访问dns-server,会轮询返回这些ip。

    当nginx成为瓶颈的时候,只要增加服务器数量,新增nginx服务的部署,增加一个外网ip,就能扩展反向代理层的性能,做到理论上的无限高并发。

    站点层的水平扩展

    站点层的水平扩展,是通过“nginx”实现的。通过修改nginx.conf,可以设置多个web后端。

    当web后端成为瓶颈的时候,只要增加服务器数量,新增web服务的部署,在nginx配置中配置上新的web后端,就能扩展站点层的性能,做到理论上的无限高并发。

    服务层的水平扩展

    服务层的水平扩展,是通过“服务连接池”实现的。

    站点层通过RPC-client调用下游的服务层RPC-server时,RPC-client中的连接池会建立与下游服务多个连接,当服务成为瓶颈的时候,只要增加服务器数量,新增服务部署,在RPC-client处建立新的下游服务连接,就能扩展服务层性能,做到理论上的无限高并发。如果需要优雅的进行服务层自动扩容,这里可能需要配置中心里服务自动发现功能的支持。

    数据层的水平扩展

    在数据量很大的情况下,数据层(缓存,数据库)涉及数据的水平扩展,将原本存储在一台服务器上的数据(缓存,数据库)水平拆分到不同服务器上去,以达到扩充系统性能的目的。

    互联网数据层常见的水平拆分方式有这么几种,以数据库为例:

    按照范围水平拆分

    每一个数据服务,存储一定范围的数据,上图为例:

    user0库,存储uid范围1-1kw

    user1库,存储uid范围1kw-2kw

    这个方案的好处是:

    (1)规则简单,service只需判断一下uid范围就能路由到对应的存储服务;

    (2)数据均衡性较好;

    (3)比较容易扩展,可以随时加一个uid[2kw,3kw]的数据服务;

    不足是:

    (1)请求的负载不一定均衡,一般来说,新注册的用户会比老用户更活跃,大range的服务请求压力会更大;

    按照哈希水平拆分

    每一个数据库,存储某个key值hash后的部分数据,上图为例:

    user0库,存储偶数uid数据

    user1库,存储奇数uid数据

    这个方案的好处是:

    (1)规则简单,service只需对uid进行hash能路由到对应的存储服务;

    (2)数据均衡性较好;

    (3)请求均匀性较好;

    不足是:

    (1)不容易扩展,扩展一个数据服务,hash方法改变时候,可能需要进行数据迁移;

    这里需要注意的是,通过水平拆分来扩充系统性能,与主从同步读写分离来扩充数据库性能的方式有本质的不同。

    通过水平拆分扩展数据库性能:

    (1)每个服务器上存储的数据量是总量的1/n,所以单机的性能也会有提升;

    (2)n个服务器上的数据没有交集,那个服务器上数据的并集是数据的全集;

    (3)数据水平拆分到了n个服务器上,理论上读性能扩充了n倍,写性能也扩充了n倍(其实远不止n倍,因为单机的数据量变为了原来的1/n);

    通过主从同步读写分离扩展数据库性能:

    (1)每个服务器上存储的数据量是和总量相同;

    (2)n个服务器上的数据都一样,都是全集;

    (3)理论上读性能扩充了n倍,写仍然是单点,写性能不变;

    缓存层的水平拆分和数据库层的水平拆分类似,也是以范围拆分和哈希拆分的方式居多,就不再展开。

    五、总结

    高并发(High Concurrency)是互联网分布式系统架构设计中必须考虑的因素之一,它通常是指,通过设计保证系统能够同时并行处理很多请求。

    提高系统并发能力的方式,方法论上主要有两种:垂直扩展(Scale Up)与水平扩展(Scale Out)。前者垂直扩展可以通过提升单机硬件性能,或者提升单机架构性能,来提高并发性,但单机性能总是有极限的,互联网分布式架构设计高并发终极解决方案还是后者:水平扩展。

    互联网分层架构中,各层次水平扩展的实践又有所不同:

    (1)反向代理层可以通过“DNS轮询”的方式来进行水平扩展;

    (2)站点层可以通过nginx来进行水平扩展;

    (3)服务层可以通过服务连接池来进行水平扩展;

    (4)数据库可以按照数据范围,或者数据哈希的方式来进行水平扩展;

    各层实施水平扩展后,能够通过增加服务器数量的方式来提升系统的性能,做到理论上的性能无限。

    展开全文
  • 本文会带你看懂分类,类扩展和匿名分类的前世今生,从看懂到会用。
  • 1.3 可扩展

    2018-01-17 11:27:59
    即使一个系统现在可以可靠地工作,但并不意味着未来它也一定会可靠地工作。造成退化的一个常见的原因...然而,它并不是一个我们可以贴到系统上的一维标签:说“X是可扩展的”或“Y不能扩展”是没有意义的。当然,讨论
  • 扩展和字扩展

    2017-07-26 18:55:00
    字位扩展 存储信息一般是存储在存储器(ROM、RAM)上的 。在实际应用中,经常出现一片ROM或RAM芯片不能满足对存储器容量需求的情况,这就需要用若干片ROM或RAM组合起来 形成一个存储容量更大的存储器。而组合方式有...
  • 新的VS支持多屏幕开发,解决了程序员们屏幕紧张的问题。昨天有机会尝试了一把,果然不错。 一、准备工作 ...如果你用的是台式机要首先确保显卡支持双头输出,或者你有一个视频转换器以及三根视频线。...
  • c# 扩展方法详解

    2019-11-15 11:16:40
    扩展方法被定义为静态方法,但它们是通过实例方法语法进行调用的。 它们的第一个参数指定该方法作用于哪个类型,并且该参数以 this 修饰符为前缀。 扩展方法当然不能破坏面向对象封装的概念,所以只能是访问所扩展类...
  • 需求缘起 ...  user(uid, name, passwd, nick)  第二版,产品经理增加了年龄,性别两个属性,表结构可能要变成:  user(uid, name, passwd, nick, age, sex) ... 假设数据量和并发量比较大,怎么变?...
  • es6之扩展运算符 三个点(...)es6之扩展运算符 三个点(...)对象的扩展运算符数组的扩展运算符总结 es6之扩展运算符 三个点(…) 对象的扩展运算符 理解对象的扩展运算符其实很简单,只要记住一句话就可以: ...
  • 1 含义扩展运算符( spread )是三个点(...)。它好比 rest 参数的逆运算,将一个数组转为用逗号分隔的参数序列。console.log(...[1, 2, 3]) // 1 2 3 console.log(1, ...[2, 3, 4], 5) // 1 2 3 4 5 [...document....
  • 1、桌面新建excel表格后,打开时,提示“Excel无法打开文件xxx.xlsx,因为文件格式或文件扩展名无效。请确定文件未损坏,并且文件扩展名与文件的格式匹配” 2、点击确认后,通过文件->新建->空白工作簿->另存为->...
  • 将旧笔记本变费为宝,作为扩展屏幕使用 转载请注明出处, by hcq908 on csdn.net, 20170105  闲置的旧笔记拿来做扩展屏正合适。但是笔记本电脑屏幕没有采集口,两台笔记本不能直接用VGA或者HDMI线连接起来实现屏幕...
  • 无法离线安装扩展,拖拽crx文件至该页面,Chrome竟然一直提示“无法从该网站添加应用,扩展程序和用户脚本”。 真是日了狗了。 如图: 鄙人是搞C++的,对前端开发虽然有兴趣,但也就是兴趣而已,实际上前端代码...
  • 扩展欧几里德算法  谁是欧几里德?自己百度去  先介绍什么叫做欧几里德算法  有两个数 a b,现在,我们要求 a b 的最大公约数,怎么求?枚举他们的因子?不现实,当 a b 很大的时候,枚举显得那么的naïve ,...
  • win7系统本身无法设置该功能(目前我是不知道哦,...第二部:安装完在扩展屏幕上便会出现任务栏 第三步:在扩展屏下任务栏中右击属性来设置相关的功能。  比如显示Windows按键 这样便解决了两个屏幕双任务栏的功能了。
  • 扩展操作码的总结

    2016-12-06 15:58:25
    需要建立的一种直观的认知是:既然是扩展操作码,就意味着操作码的位数越变越多! 之所以这么强调,是因为常常混淆了操作码的扩展方向。再看扩展的原理: 假设指令字长是16位,平均劈开成4份,高位4位用作操作码,...
  • Kotlin系列之扩展函数

    2019-04-22 23:53:30
    简述: 今天带来的是Kotlin浅谈系列的第五弹,这讲主要是讲利用Kotlin中的扩展函数特性让我们的代码变得更加简单和整洁。扩展函数是Kotlin语言中独有的新特性,利用它可以减少很多的样板代码,大大提高开发的效率;...
1 2 3 4 5 ... 20
收藏数 2,940,153
精华内容 1,176,061
关键字:

扩展