HihoCoder – 1449 后缀自动机三·重复旋律6 后缀自动机、递推、DFS

ProLightsfx 2017-4-22 144 4/22

后缀自动机三·重复旋律6 后缀自动机、递推、DFS

Source

HihoCoder - 1449

 

My Solution

题意:求一个字符串中,所有长度为K的子串出现次数最多的子串的出现次数,但是K不是固定的,求所有的K的答案。

 

后缀自动机、递推、DFS

首先 ans[MAXN] 必定是单调不增序列,

一个子串出现的次数是它的endpos集合的大小,由于endpos[u]的集合为以u代表的子树的endpos集合的并集,可以跑一边dfs,预处理出所有的endpossz[i]。

所以只需要根据pre树求出,ans[maxlen(st)] = max(ans[maxlen[st], endpossz[st]),然后从len~0递推,ans[i] = max(ans[i], ans[i+1])。

复杂度 O(n)

 

#include 
#include 
#include 
#include 
#include 
using namespace std;
typedef long long LL;
const int MAXN = 2*1e6 + 8;

string s;
struct SAM{
    int ch[MAXN][26], pre[MAXN], val[MAXN], endpos[MAXN], endpossz[MAXN];
    int last, tot;
    void init(){
        last = tot = 0;
        memset(ch[0], -1, sizeof ch[0]);
        pre[0] = -1; val[0] = 0;
    }
    void extend(int c, int ind){
        int p = last, np = ++tot;
        val[np] = val[p] + 1; endpos[np] = ind;
        memset(ch[np], -1, sizeof ch[np]);
        while(~p && ch[p][c] == -1) ch[p][c] = np, p = pre[p];
        if(p == -1) pre[np] = 0;
        else{
            int q = ch[p][c];
            if(val[q] != val[p] + 1){
                int nq = ++tot;
                memcpy(ch[nq], ch[q], sizeof ch[q]);
                val[nq] = val[p] + 1;
                pre[nq] = pre[q];
                pre[q] = pre[np] = nq;
                while(~p && ch[p][c] == q) ch[p][c] = nq, p = pre[p];
            }
            else pre[np] = q;
        }
        last = np;
    }
    vector sons[2*MAXN];
    void build_the_tree(){
        for(int i = 1; i <= tot; i++){ sons[pre[i]].push_back(i); } } void get_endpos_sz(int u){ int sz = sons[u].size(), i; if(endpos[u] > 0) endpossz[u] = 1;
        else endpossz[u] = 0;
        for(i = 0; i < sz; i++){
            get_endpos_sz(sons[u][i]);
            endpossz[u] += endpossz[sons[u][i]];
        }
    }
    int ans[MAXN];
    void run(int n){
        memset(ans, 0, sizeof ans);
        for(int i = 1; i <= tot; i++){ ans[val[i]] = max(ans[val[i]], endpossz[i]); } for(int i = n - 1; i >= 1; i--){
            ans[i] = max(ans[i], ans[i+1]); //从后往前维护
        }
    }

} sam;

int main()
{
    #ifdef LOCAL
    freopen("22.in", "r", stdin);
    //freopen("22.out", "w", stdout);
    int T = 2;
    while(T--){
    #endif // LOCAL
    ios::sync_with_stdio(false); cin.tie(0);

    int n, i;
    cin >> s;
    n = s.size();
    sam.init();
    for(i = 0; i < n; i++) sam.extend(s[i] - 'a', i+1);
    sam.build_the_tree();
    sam.get_endpos_sz(0);
    sam.run(n);
    for(i = 1; i <= n; i++){
        cout << sam.ans[i] << "n";
    }

    #ifdef LOCAL
    cout << endl;
    }
    #endif // LOCAL
    return 0;
}

 


非特殊说明,本博所有文章均为博主原创,未经许可不得转载。

https://www.prolightsfxjh.com/

Thank you!

                                                                                                                                             ------from ProLightsfx

- THE END -

ProLightsfx

11月15日16:44

最后修改:2024年11月15日
0

非特殊说明,本博所有文章均为博主原创,未经许可不得转载。

共有 0 条评论