012.匹配
匹配两个字符串
- 母串为 s 、子串为 t
- 当 t 在 s 中出现至少一次,匹配成功
- 匹配失败返回 -1
朴素匹配
当 t 的长度很短时,在 s 上枚举起点
int match(string &s,string &t){
int lt=t.length();
int ls=s.length();
for(int st=0;st+lt<=ls;st++){
int i=st,j=0;
while(j<lt&&s[i]==t[j])j++,i++;
if(j==lt)return st;
}
return -1;
}
kmp
用于 t 较长时
vector<int> get_next(string &t){
int n=t.length();
vector<int>next(n);
next[0]=-1,next[1]=0;
int j=2,cn=0;
while(j<n){
if(t[j-1]==t[cn])next[j++]=++cn;
else if(cn)cn=next[cn];
else next[j++]=0;
}
return next;
}
int kmp(string&s,string t){
vector<int>next=get_next(t);
int ls=s.length(),lt=t.length();
int i=0,j=0;
while(i<ls&&j<lt){
if(s[i]==t[j])j++,i++;
else if(j==0)i++;
else j=next[j];
}
return j==lt?i-j:-1;
}
当然,可以合成一个函数
int kmp(string&s,string t){
int ls=s.length(),lt=t.length();
vector<int>next(lt);
next[0]=-1,next[1]=0;
int j=2,cn=0;
while(j<lt){
if(t[j-1]==t[cn])next[j++]=++cn;
else if(cn)cn=next[cn];
else next[j++]=0;
}
int i=0,j=0;
while(i<ls&&j<lt){
if(s[i]==t[j])j++,i++;
else if(j==0)i++;
else j=next[j];
}
return j==lt?i-j:-1;
}
RabinKarp
利用哈希思想解码
int RabinKarp(string &s,string &t){
int R=256;
int L=t.length();
int mod=1658598167;//一个较大的素数,减少哈希冲突
int RL=1;
for(int i=1;i<L;++i){
RL=(RL*R)%mod;
}
long key_t=0;
for(int i=0;i<L;i++){
key_t=(key_t*R+t[i])%mod;
}
long key=0;
int l=0,r=0;
while(r<(int)s.length()){
key=(key*R+s[r++]);
while(r-l==L){
if(key==key_t&&t.compare(s.substr(l,L))==0)//哈希冲突,需cmp
return l;
key=(key-RL*s[l++])%mod;
}
}
return -1;
}

浙公网安备 33010602011771号