zoukankan      html  css  js  c++  java
  • 【模板】后缀自动机 (SAM)【SAM解法】

    I.【模板】后缀自动机 (SAM)

    虽说是模板但也不是纯粹板子!

    SAM应用1:求一个子串的出现次数(相当于字符串匹配)。

    因为同一个 \(\text{endpos}\) 类中所有东西的结束集合都是相同的,故它们在母串中的出现次数也是相同的。因此,在该类中就应该贪心地选择最长的串,也即 \(\text{len}\)

    那么我们如何求出一个 \(\text{endpos}\) 类中所有东西的出现次数呢?考虑Parent Tree。

    Parent Tree的实质是往一个集合中的串的开头添加新字符的过程。于是,我们考虑DP。设 \(f_i\) 表示集合 \(i\) 中所有串的出现次数。则 \(f_i=1+\sum\limits_{j\text{是}i\text{的儿子}}f_j\)。其中,那个 \(1\) 是指不加任何数的串本身。

    时间复杂度 \(O(n|\Sigma|)\)

    代码:

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    const int N=1001000;
    struct Suffix_Automaton{int ch[26],len,fa;}t[N<<1];//a SAM has 2n nodes!!!
    int f[N<<1];
    int cnt=1;
    int Add(int x,int c){//add a character c after node x,return the index.
    	int xx=++cnt;//the index of the newly-added node
    	f[xx]=1;//stands that x is a finishing point
    	t[xx].len=t[x].len+1;//the maximal length of strings in xx.
    	for(;x&&!t[x].ch[c];x=t[x].fa)t[x].ch[c]=xx;
    	if(!x){t[xx].fa=1;return xx;}
    	int y=t[x].ch[c];
    	if(t[y].len==t[x].len+1){t[xx].fa=y;return xx;}
    	int yy=++cnt;t[yy]=t[y];
    	t[yy].len=t[x].len+1;
    	t[y].fa=t[xx].fa=yy;
    	for(;x&&t[x].ch[c]==y;x=t[x].fa)t[x].ch[c]=yy;
    	return xx;
    }
    int n;
    char s[N];
    vector<int>v[N<<1];
    void dfs(int x){for(auto y:v[x])dfs(y),f[x]+=f[y];}
    ll res;
    int main(){
    	scanf("%s",s),n=strlen(s);
    	for(int i=0,las=1;i<n;i++)las=Add(las,s[i]-'a');
    	for(int i=2;i<=cnt;i++)v[t[i].fa].push_back(i);
    	dfs(1);
    	for(int i=1;i<=cnt;i++)if(f[i]!=1)res=max(res,1ll*f[i]*t[i].len);
    	printf("%lld\n",res);
    	return 0;
    }
    

  • 相关阅读:
    团队冲刺阶段二(八)
    团队项目事后诸葛亮会议
    团队冲刺阶段二(七)
    团队冲刺阶段二(六)
    团队冲刺阶段二(五)
    团队冲刺阶段二(四)
    HTML5 CSS3
    浮动和渐变色,定位position,元素的层叠顺序
    css盒模型。边框和内外边距
    标签分类与元素转换
  • 原文地址:https://www.cnblogs.com/Troverld/p/14605540.html
Copyright © 2011-2022 走看看