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

    每个子串的出现次数就是其后缀自动机上所在节点的endpos等价类集合的大小。

    代码:

    #include<cstdio>
    #include<cstring>
    #include<iostream>
    #include<algorithm>
    
    using namespace std;
    
    const int N=3000009;
    char s[N];
    int n;
    struct Suffix_DFA
    {
    	int Siz,last;
    	struct Dot
    	{
    		int len,link,ch[30],end;
    	}sam[N];
    	int head[N],cnt,Ans;
    	struct Edge
    	{
    		int nxt,to;
    	}g[N*2];
    	
    	void add(int from,int to)
    	{
    		g[++cnt].nxt=head[from];
    		g[cnt].to=to;
    		head[from]=cnt;
    	}
    	
    	void init()
    	{
    		sam[0].link=-1;
    	}
    	
    	void SAM_Extend(int k)
    	{
    		int cur=++Siz;
    		sam[cur].len=sam[last].len+1,sam[cur].end=1;
    		int p=last;
    		while(p!=-1&&!sam[p].ch[k])
    			sam[p].ch[k]=cur,
    			p=sam[p].link;
    		if(p==-1)
    			sam[cur].link=0;
    		else
    		{
    			int q=sam[p].ch[k];
    			if(sam[q].len==sam[p].len+1)
    				sam[cur].link=q;
    			else
    			{
    				int clone=++Siz;
    				sam[clone].len=sam[p].len+1;
    				sam[clone].link=sam[q].link;
    				for (int i=1;i<=26;i++)
    					sam[clone].ch[i]=sam[q].ch[i];
    				while(p!=-1&&sam[p].ch[k]==q)
    					sam[p].ch[k]=clone,
    					p=sam[p].link;
    				sam[q].link=sam[cur].link=clone;
    			}
    		}
    		last=cur;
    	}
    	
    	void build()
    	{
    		for (int i=1;i<=Siz;i++)
    			add(sam[i].link,i);
    	}
    	
    	void dfs(int x)
    	{
    		for (int i=head[x];i;i=g[i].nxt)
    		{
    			int v=g[i].to;
    			dfs(v);
    			sam[x].end+=sam[v].end;
    		}
    		Ans=max(Ans,(sam[x].end==1?0:sam[x].end)*sam[x].len);
    	}
    	
    	int Get_Ans()
    	{
    		build(),dfs(0);
    		return Ans;
    	}
    }A;
    
    void init()
    {
    	scanf("%s",s+1);
    }
    
    void work()
    {
    	n=strlen(s+1),A.init();
    	for (int i=1;i<=n;i++)
    		A.SAM_Extend(s[i]-'a'+1);
    	printf("%d
    ",A.Get_Ans());
    }
    
    int main()
    {
    	init();
    	work();
    	return 0;
    }
    
    由于博主比较菜,所以有很多东西待学习,大部分文章会持续更新,另外如果有出错或者不周之处,欢迎大家在评论中指出!
  • 相关阅读:
    minix中的文件锁
    minix代码中conv2()函数的作用
    ClassView中视图类框架类不见了的解决方法
    minix中的GDT,LDT,IDT和TSS
    MFC dlg窗口按回车(Enter)键和ESC键会退出解决方法
    MongoDB文档、集合、数据库简介
    Windows下MongoDB环境搭建
    【译】RabbitMQ:"Hello World"
    转载 jQuery技巧
    android call webservice by ksoap 实例代码
  • 原文地址:https://www.cnblogs.com/With-penguin/p/13341880.html
Copyright © 2011-2022 走看看