zoukankan      html  css  js  c++  java
  • 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;
    }
    
  • 相关阅读:
    python3 入门
    Python2 的列表排序
    数据库阻塞SQL的隔离级别
    数据库阻塞讲解设计应用程序时避免阻塞的八个准则
    DELPHI学习简单类型
    DELPHI学习结构类型
    InsideVCL第3章面向对象程序语言和Framework
    数据库阻塞分析死锁并处理
    面向对象开发实践之路
    DELPHI hint 的应用
  • 原文地址:https://www.cnblogs.com/SovietPower/p/9241275.html
Copyright © 2011-2022 走看看