其他分享
首页 > 其他分享> > 7.17 Graph&String

7.17 Graph&String

作者:互联网

\[\begin{aligned}\begin{gathered}\ \huge\mathcal{G}\texttt{raph&}\mathcal{S}\texttt{tring} \quad{\large\texttt{-Zhang_RQ}} \end{gathered}\end{aligned} \]

Tarjan

差分约束

等价变形为 \(x_i\leq x_j+c_k\),与最短路的松弛条件很相似,所以可以从 \(j\) 向 \(i\) 建一条 \(c_k\) 的边,再新建 \(0\) 号点向所有点连边,边权为 \(0\),从 \(0\) 号点开始跑单源最短路,如果有负环证明无解。

注:判负环应使用 Bellman-Ford 或 队列优化的 Bellman-Ford (某已死算法)。

欧拉图

欧拉图的判定

Hierholzer 算法

二分图

二分图判定

二分图最大匹配

原理:不断寻找增广路径,并通过递归实现 “撤销和更换” 操作。

霍尔定理

对于任何左部点的子集 \(S\) 都要满足 \(\left|S\right|\leq\left|T\right|\),其中 \(T\) 表示 \(S\) 中的点能到达右部点的并。

Hash

多项式 Hash

对于一个长度为 \(l\) 的字符串 \(s\) 而言,我们定义多项式 \(f_s=\sum_{i=1}^m s_i\times b^{l-i} \pmod P\) 为字符串 \(s\) 的 Hash 函数,实际上也可以将其理解为字符串 \(s\) 在 \(b\) 进制下的结果。

允许 \(k\) 次失配的字符串匹配

无法使用 KMP,但是可以 Hash + 二分。

枚举所有可能匹配的子串,假设现在枚举的子串为 \(s'\),通过 Hash + 二分可以快速找到 \(s'\) 和 \(p\) 第一个不同的位置。之后将 \(s'\) 和 \(p\) 在这个失配位置以及之前的部分删掉,继续查找下一个失配位置,这样的过程最多发生 \(k\) 次。

时间复杂度:\(O(m+kn\log m)\)

KMP

\(\rm nxt_i\) 求法:

for(int i=2,j=0;i<=m;i++){
    while(j&&p[j+1]!=p[i])
        j=nxt[j];
   	if(p[j+1]==p[i])
        j++;
    nxt[i]=j;
}

匹配做法:

for(int i=1,j=0;i<=n;i++){
	while(j&&p[j+1]!=s[i])
        j=nxt[j];
    if(p[j+1]==s[i])
        j++;
    if(j==m){
        ans[++cnt]=i-m+1;
        j=nxt[j];
    }
}

Trie 树

int next[N][26],cnt;
int num[N];
//插入
void insert(char *s,int l){
    int p=0;
    for(int i=0;i<l;i++){
        int ch=s[i]-'a';
        if(!next[p][c]) next[p][c]=++cnt;
        p=next[p][c];
    }
    num[p]++;
}
//查询
int find(char *s,int l){
    int p=0;
    for(int i=0;i<l;i++){
        int ch=s[i]-'a';
        if(!next[p][c]) return 0;
        p=next[p][c];
    }
    return num[p];
}

AC 自动机

建立 AC 自动机的步骤

\(\rm Fail\) 指针

\(\rm Fail\) 求法:

void build(){
	for(int i=0;i<26;i++)
        if(tr[0][i]) q.push(tr[0][i]);
    while(q.size()){
        int u=q.front();
        q.pop();
        for(int i=0;i<26;i++){
            if(tr[u][i]){
                fail[tr[u][i]]=tr[fail[u]][i];
                q.push(tr[u][i]);
            }else tr[u][i]=tr[fail[u]][i];
        }
    }
}

多模式匹配:

int query(char *t){
    int u=0,res=0;
    for(int i=1;t[i];i++){
        u=tr[u][t[i]-'a'];
        for(int j=u;j&&e[j]!=-1;j=fail[j]){
            res+=e[j];e[j]=-1;
        }
    }
    return res;
}

时间复杂度:\(O(26n+m)\),其中 \(n\) 为节点数,\(m\) 为源串长度。

Manacher

标签:7.17,匹配,String,int,Graph,leq,rm,字符串,Hash
来源: https://www.cnblogs.com/blueqwq/p/15023798.html