• BZOJ.2882.工艺(后缀自动机 最小表示 map)


    题目链接 BZOJ
    洛谷

    SAM求字符串的最小循环表示。
    因为从根节点出发可以得到所有子串,所以每次找字典序最小的一个出边走即可。因为长度问题把原串再拼接在后面一次。
    需要用map存转移。复杂度O(nlogn)。
    当然还有O(n)的最小表示法。
    (在BZOJ上慢的一批啊QAQ)

    //73240kb	2496ms
    #include <map>
    #include <cstdio>
    #include <cctype>
    #include <algorithm>
    #define gc() getchar()
    const int N=(3e5+5)*4;
    
    inline int read()
    {
    	int now=0;register char c=gc();
    	for(;!isdigit(c);c=gc());
    	for(;isdigit(c);now=now*10+c-'0',c=gc());
    	return now;
    }
    struct Suffix_Automaton
    {
    	int n,s[N],las,tot,fa[N],len[N];
    	std::map<int,int> son[N];
    
    	void Insert(int c)
    	{
    		int p=las,np=++tot; len[las=np]=len[p]+1;
    		for(; p&&!son[p].count(c); p=fa[p]) son[p][c]=np;
    		if(!p) fa[np]=1;
    		else
    		{
    			int q=son[p][c];
    			if(len[q]==len[p]+1) fa[np]=q;
    			else
    			{
    				int nq=++tot;
    				len[nq]=len[p]+1, son[nq]=son[q];
    				fa[nq]=fa[q], fa[q]=fa[np]=nq;
    				for(; son[p][c]==q; p=fa[p]) son[p][c]=nq;
    			}
    		}
    	}
    	void Build()
    	{
    		n=read(), las=tot=1;
    		for(int i=1; i<=n; ++i) Insert(s[i]=read());
    		for(int i=1; i<=n; ++i) Insert(s[i]);
    	}
    	void Solve()
    	{
    		std::map<int,int>::iterator it;
    		for(int i=1,p=1; i<=n; ++i)
    			it=son[p].begin(), p=it->second, printf("%d ",it->first);//别混了map的first(转移)与second(son)啊 
    	}
    }sam;
    
    int main()
    {
    	sam.Build(), sam.Solve();
    	return 0;
    }
    
  • 相关阅读:
    Nginx负载均衡配置实例详解
    Tomcat服务器
    如何设计安全的用户登录功能
    Tomcat 配置用户认证服务供C#客户端调用
    DataWindow值获取
    弹出上下文菜单
    DataWindow快速从Grid格式转为Freefrom
    postEvent() @ triggerEvent
    日期赋值为: 0000:00:00
    截取字符串
  • 原文地址:https://www.cnblogs.com/SovietPower/p/9241275.html
Copyright © 2020-2023  润新知