zoukankan      html  css  js  c++  java
  • SPOJ 8222 Substrings

    题面

    Description

    给长度为 n 的字符串 S , 对任意的 L , 求长度为 L 的子串最多出现的次数.

    Input

    String S consists of at most 250000 lowercase latin letters.

    Output

    Output |S| lines. On the i-th line output F(i).

    Sample Input

    ababa
    Sample Output
    3
    2
    2
    1
    1
    

    题解

    后缀自动机统计子串出现次数的应用.
    考虑我们插入一个节点时, 其suffix link上的所有节点所代表的字符串的出现次数都+1, 因此parent tree上一个节点所代表的字符串的出现次数等于以它为根的子树中实点的出现次数.
    线段树上成段更新来维护即可.

    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #include <vector>
    
    const int LEN = 250000;
    
    struct segmentTree
    {
    	int a[LEN << 2];
    
    	inline segmentTree()
    	{
    		memset(a, 0, sizeof(a));
    	}
    
    	void modify(int u, int curL, int curR, int L, int R, int w)
    	{
    		if(curL >= L && curR <= R)
    		{
    			a[u] = std::max(a[u], w);
    			return;
    		}
    		int mid = curL + curR >> 1;
    		if(L <= mid)
    			modify(u << 1, curL, mid, L, R, w);
    		if(R > mid)
    			modify(u << 1 | 1, mid + 1, curR, L, R, w);
    	}
    
    	inline void modify(int L, int R, int w)
    	{
    		modify(1, 1, LEN, L, R, w);
    	}
    
    	int query(int u, int L, int R, int pos)
    	{
    		if(L == R)
    			return a[u];
    		int mid = L + R >> 1;
    		if(pos <= mid)
    			return std::max(a[u], query(u << 1, L, mid, pos));
    		else
    			return std::max(a[u], query(u << 1 | 1, mid + 1, R, pos));
    	}
    
    	inline int query(int pos)
    	{
    		return query(1, 1, LEN, pos);
    	}
    }sgt;
    
    struct suffixAutomaton
    {
    	struct state
    	{
    		state *suc[26], *pre;
    		std::vector<state*> sucOnTr;
    		int len, sz, tg;
    
    		inline state()
    		{
    			for(int i = 0; i < 26; ++ i)
    				suc[i] = NULL;
    			sucOnTr.clear();
    			sz = tg = 0;
    		}
    	};
    
    	state *rt, *lst;
    
    	inline void insert(int c)
        {
            state *u = new state;
            u->len = lst->len + 1;
            u->sz = 1;
            for(; lst != NULL && lst->suc[c] == NULL; lst->suc[c] = u, lst = lst->pre);
            if(lst == NULL)
                u->pre = rt;
            else
            {
                state *p = lst->suc[c];
                if(p->len == lst->len + 1)
                    u->pre = p;
                else
                {
                    state *q = new state;
                    *q = *p;
                    q->sz = 0;
                    q->len = lst->len + 1;
                    p->pre = u->pre = q;
                    for(; lst != NULL && lst->suc[c] == p; lst->suc[c] = q, lst = lst->pre);
                }
            }
            lst = u;
        }
    
    	inline void build(char *str, int len)
    	{
    		lst = rt = new state;
    		rt->len = 0, rt->pre = NULL;
    		for(int i = 0; i < len; ++ i)
    			insert(str[i] - 'a');
    	}
    
    	void getSucessorOnSuffixTree(state *u)
    	{
    		u->tg = 1;
    		if(u->pre != NULL)
    			u->pre->sucOnTr.push_back(u);
    		for(int i = 0; i < 26; ++ i)
    			if(u->suc[i] != NULL && ! u->suc[i]->tg)
    				getSucessorOnSuffixTree(u->suc[i]);
    	}
    
    	void DFS(state *u)
    	{
    		for(std::vector<state*>::iterator p = u->sucOnTr.begin(); p != u->sucOnTr.end(); ++ p)
    			DFS(*p), u->sz += (*p)->sz;
    		if(u != rt)
    			sgt.modify(u->pre->len + 1, u->len, u->sz);
    	}
    
    	inline void work()
    	{
    		getSucessorOnSuffixTree(rt);
    		DFS(rt);
    	}
    }SAM;
    
    int main()
    {
    	#ifndef ONLINE_JUDGE
    	freopen("SPOJ8222.in", "r", stdin);
    	#endif
    	static char str[LEN];
    	scanf("%s", str);
    	int len = strlen(str);
    	SAM.build(str, len);
    	SAM.work();
    	for(int i = 1; i <= len; ++ i)
    		printf("%d
    ", sgt.query(i));
    }
    
  • 相关阅读:
    AJAX基础
    DOM事件机制(事件捕获和事件冒泡和事件委托)
    http协议
    DOM实战-js todo
    python常见面试题
    jQuery快速入门
    三级菜单
    购物车
    员工信息表
    random模块
  • 原文地址:https://www.cnblogs.com/ZeonfaiHo/p/7126672.html
Copyright © 2011-2022 走看看