首先了解一下什么是最长相同前后缀,即一个字符串相同的前缀和后缀的最大长度。
一个字串,产生一个next数组,数组的每一个值就代表字符串从0到该索引值的子串的最长前后缀。
比如ABAB的子串,next={0,0,1,2},"A"只有一个数;"AB"因为没有相同前后缀故为0;"ABA"可以发现前缀A和后缀A相同,长度为1;"ABAB"有相同前缀AB,长度为2。kmp算法的核心就是最长相同前后缀,而next数组就是为了记录每个子串的最长相同前后缀。
传统的字符串匹配算法,即原串与每个串比较,如果相同则两边加1,不同则子串回到首位,原串回到下一位。而kmp算法可以只遍历一次原串。比如:
CBABABABC
ABABC
00 12
在匹配到C的时候,发现不相同,那么可以使j跳过next[j-1],也就是2。
CBABABABC
ABABC
00 12
01 2 3
为什么可以这么做呢。因为2代表的是最长相同前后缀,后缀的使用在第一次匹配时用过了,因为前缀和后缀是相同的,所以第二次匹配时可以跳过前缀,因为这在第一次匹配后缀的时候匹配过了,那么可以跳过多少呢?就是相同前后缀的最大长度。这样就可以节省时间,原串不用回溯了,这是kmp算法的原理。
那么怎么算next数组呢?
ABABC
00 12
有个要注意的点,那就是相同前后缀的最大长度其实就是前缀末尾的索引值+1,比如第三个A的相同前后缀最大长度为1,就是相同前缀末尾A的索引值(0)+1。所以如何求出相同前后缀的最大长度呢?比如后面的B,它只需对比自己和索引值为前一个next值的数值是否相等,如果相等则最大长度加1即可。比如B,比较索引值为1的B,相等就加1,算出2。
如果不相等,那需要回溯,这样求next数组的时间复杂度就变成O(n^2)。我们要把它变成O(n)。
具体做法还是用到最长相同前后缀的思想,不相等也就是要重新找前缀,可以发现前缀和后缀不是相等的吗,最后一个next值就记录了前缀长度,所以通过后缀找到前缀的长度。而前缀的最后一个next值就记录了能匹配的最大相同长度。也就是跳过后缀直接找到前缀,在前缀作匹配,经过两层前后缀套娃。比如
ABABA
0 0 12
A跳过后缀到前缀AB,前缀中记录了最长相同前后缀长度为0,所以A跟索引值为0的A作比较,相等就加1,所以得到1。
代码如下:
vector<int> next(len1);
for(int i=1;i<len1;i++){
if(s1[i]==s1[next[i-1]]){
next[i]=next[i-1]+1;
}else{
if(next[next[i-1]]-1<0){
next[i]=0;
continue;
}
int pre=next[next[next[i-1]]-1];
if(s1[pre]==s1[i]){
next[i]=pre+1;
}else{
next[i]=0;
}
}
}
而kmp匹配代码如下:
int i=0,j=0;
while(i<2*len1&&j<len1){
if(j==0||s3[i]==s1[j]){
i++;
j++;
}else{
j=next[j-1];
}
}
leetcode有道例题
面试题 01.09. 字符串轮转
waterbottle旋转得到erbottlewat,反之亦然。
怎么通过一次检查就能知道是否能旋转得到呢?
我们试试s2加上自身,得到erbottlewaterbottlewat,找到子串waterbottle。再把去掉得到erbottlewat,与原来的s2对比,如果相等则可以旋转得到,否则不行。
aa,aba
aba加上自身得到abaaba,abba!=aba。
这几天遇到的问题:
如果要前端发送cookie到后端,那么后端在跨域设置中要这样设置:
response['Access-Control-Allow-Origin'] = "http://"
response['Access-Control-Allow-Headers'] = "Origin, X-Requested-With, Content-Type, Accept, Cookie,Access-Token"
response['Access-Control-Allow-Methods'] = 'GET,POST,OPTIONS'
response['Access-Control-Allow-Credentials']="true"
response['Access-Control-Expose-Headers']='*'
最重要的是当’Access-Control-Allow-Credentials’设置为’true’时,'Access-Control-Allow-Origin’不能设置为‘*’,而只能是一个固定ip。
但是现在新版chrome设置了限制,不是同源网站都不能发送cookie,因为samesite默认latx。可以设置samesite为None,但是必须同时要求security为true,也就是设置https安全证书。大一时遇到过这个问题,但是当时用火狐展示就能解决,所以没有过于注意。没想到一年多后再次遇到找不出问题,折腾了一天。
周四分配任务。