字符串
KMP
void get_nex(string &s){
int j=0,k=-1;
nex[0]=-1;
while(j<(int)s.size()){
if(k==-1 || s[j]==s[k]){
j++; k++;
nex[j]=k;
}else{
k=nex[k];
}
}
}
int KMP(string &s1,string &s2){
int i=0,j=0;
get_nex(s2);
while(i<(int)s1.size() && j<(int)s2.size()){
if(j==-1 || s1[i]==s2[j]){
i++,j++;
// if(j>=(int)s2.size()){
// ans.push_back( i-(int)s2.size() );
// j=nex[j];
// }
}else{
j=nex[j];
}
}
if(j>=(int)s2.size()) return i-(int)s2.size();
return -1;
}
哈希
哈希匹配
理论时间复杂度(m+n),B为一个质数,随意取,哈希算法不是100%准确,有一定概率会出错.
(当然我们也可以在哈希值相同的时候再用朴素双法再次进行检验,以达到100%的匹配准确)
大多数情况下,哈希检索的速度都是非常快的
int lena,lenb;
char a[1005],b[1005];//查找a中的b
int B=131;//质数基13331
void hash_pipei(){
if(lenb>lena)
return;
ll hash_b=0,hash_a=0;
ll t=1;//作中间变量存储B^t;
for(int i=0;i<lenb;i++){
hash_b=hash_b*B+b[i];
t*=B;
hash_a=hash_a*B+a[i];
}
if(hash_a==hash_b){
printf("YES\n");
}
for(int i=lenb;i<lena;i++){
hash_a=hash_a*B-t*a[i-lenb]+a[i];
if(hash_a==hash_b){
printf("%d YES\n",i);
}
}
}
时间复杂度(1)的询问子串哈希
const ll mod1 = 1e9+7;
const ll mod2 = 1e9+9;
char s[N];
ll base1[N],base2[N];
ll p_h1[N],p_h2[N];
ll p_h3[N],p_h4[N];//回文
inline ll query( int l,int r,int key ){//O(1) 询问hash值
if( key ) return ((p_h1[r]-p_h1[l-1]*base1[r-l+1]%mod1)+mod1)%mod1;
return ((p_h2[r]-p_h2[l-1]*base2[r-l+1]%mod2)+mod2)%mod2;
}
inline ll query2( int l,int r,int key ){//回文
if( key ) return ((p_h3[r]-p_h3[l-1]*base1[r-l+1]%mod1)+mod1)%mod1;
return ((p_h4[r]-p_h4[l-1]*base2[r-l+1]%mod2)+mod2)%mod2;
}
inline bool Palindrome( int l,int r ){//回文
return ( query(l,r,1 )==query2( n-r+1,n-l+1,1 ) && query(l,r,0)==query2( n-r+1,n-l+1,0) );
}
void hash_val(){
base1[0]=1; base2[0]=1;
ll B=13331;
for(int i=1;i<=n;i++){
base1[i]=base1[i-1]*B%mod1;
base2[i]=base2[i-1]*B%mod2;
}
for(int i=1;i<=n;i++){
p_h1[i]=( p_h1[i-1]*B + s[i] )%mod1;
p_h2[i]=( p_h2[i-1]*B + s[i] )%mod2;
//回文
p_h3[i]=( p_h3[i-1]*B + s[n-i+1] )%mod1;
p_h4[i]=( p_h4[i-1]*B + s[n-i+1] )%mod2;
}
}
字典树
int nex[100000][26], cnt;
bool exist[100000]; // 该结点结尾的字符串是否存在
void insert(char *s, int len) { // 插入字符串
int p = 0,c;
for (int i = 0; i < len; i++) {
c = s[i] - 'a';
if (!nex[p][c]) nex[p][c] = ++cnt; // 如果没有,就添加结点
p = nex[p][c];
}
exist[p] = 1;
}
bool find(char *s, int len) { // 查找字符串
int p = 0,c;
for (int i = 0; i < len; i++) {
c = s[i] - 'a';
if (!nex[p][c]) return 0;
p = nex[p][c];
}
return exist[p];
}
马拉车算法
string Manacher(string &s){
string t="@#";
for(int i=0;i<s.size();i++){
t+=s[i]; t+="#";
}
vector<int> p(t.size(),0);
int mx=0,id=0,resLen=0,resCenter=0;
for(int i=1;i<t.size();i++){
p[i]=mx>i?min(p[2*id-i],mx-i):1;
while( t[i+p[i]]==t[i-p[i]] ) ++p[i];
if(mx<i+p[i]){
mx=i+p[i];
id=i;
}
if(resLen<p[i]){
resLen=p[i];
resCenter=i;
}
}
return s.substr( (resCenter-resLen)/2,resLen-1 );
}