KMP,Hash,Trie学习笔记

KMP,Hash,Trie学习笔记

今天我们来讲下字符串更深入点的内容,KMP,Hash,Trie。

KMP算法

OI Wiki

我也并不是很懂,本质上,记住怎么用和板子可以了。

Code for KMP:
int j=0;
for(int i=1;i<=n;i++){
    while(j&&a[j+1]!=a[i]) j=kmp[j];
    if(a[j+1]==a[i]) j++;
    kmp[i]=j;
}
练习题

KMP模板
KMP+LCA
KMP思维题
KMP较难题

Hash 算法:

OI Wiki
字符串哈希是一种可以用于快速比较字符串的算法,通过加上上一项,再乘上 \(base\),接着模上 \(mod\) 而加密成一个神秘的数字,且无法回推, \(mod\) 常取一些大质数,如 \(998244353\)\(1000000007\) 等。\(base\) 常取 \(13331\) 等,通过类似前缀和查询的方式查询字符串加密后的值。

Code for Hash:
void build(){  
    int base=13331,mod=998244353;
    for(int i=1;i<=n;i++){
        hash[i]=(hash[i-1]*base+s[i])%mod;
        pw[i]=(pw[i-1]*base)%mod;
    }
}
int query(int l,int r){
    if(l>r) return 0;
    return ((hash[r]-hash[l-1]*pw[r-l+1])%mod+mod)%mod;
}
练习题:

Hash模板
Hash思维题
Hash较难题1
Hash较难题2

Trie 算法:

OI Wiki
Trie 又名字典树,是一种树形数据结构,以字符为边,节点按序号排列,插入时,若有前缀相同的子树,便将除前缀外的部分插入在该子树下面。查询时,按字符遍历,走与字符相同的边即可。

Code for Trie
int tr[3000005][27],tot=1,cnt[3000005];
void insert(string str){
    int p=1;
    for(int i=0;i<str.size();i++) {
        int u=str[i]-'a';
        if(!tr[p][u]) tr[p][u]=++tot;
        p=tr[p][u];
    }
}
int query(string str){ //查询以str为前缀的字符串数量
    int p=1;
    for(int i=0;i<str.size();i++){
        int u=str[i]-'a';
        if(!tr[p][u]) return 0;
        p=tr[p][u];
    }
    return cnt[p];
}
练习题:

Trie 模板
Trie 水题

小扩展:01 Trie

01 Trie 本质上根 Trie 差不多,只是边权变成了 0 或 1,通常出理二进制问题,如最大异或和等。

Code for 01Trie
int tr[3000005][2],cnt[3000005],tot=1;
void insert(int x){
    int p=1;
    for(int i=30;i>=0;i--){
        int u=x>>i&1;
        if(!tr[p][u]) tr[p][u]=++tot;
        p=tr[p][u];
        cnt[p]++;
    }
}
int query(int x,int k){//求当中子序列异或和 >=k 的数量
    int p=1,ans=0;
    for(int i=30;i>=0;i--){
        int u=x>>i&1,v=k>>i&1;
        if(v==1) p=tr[p][u^1];
        else{
            ans+=cnt[tr[p][u^1]];
            p=tr[p][u];
        }
    }
    ans+=cnt[p];
    return ans;
}

01Trie 题目1
01Trie 题目2

posted on 2025-08-12 19:16  hhr_qwq  阅读(7)  评论(0)    收藏  举报