zoukankan      html  css  js  c++  java
  • 洛谷3804 【模板】后缀自动机

    传送门

    真·玄学

    还是没有完全搞懂SAM的性质啥的啊T^T

    我本来以为SAM会很长的没想到这么短

    这个题就是建出SAM 然后建树求出right然后*len[max]直接取max即可啦

    学习笔记什么的等等吧[鸽了我也不管]

    附代码。

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<cmath>
    #define inf 20021225
    #define ll long long
    #define mxn 1000100
    using namespace std;
    
    struct node{int ch[26],len,fa,sz;}t[mxn*4];
    struct edge{int to,lt;}e[mxn*4];
    int poi,lt,rt,cnt,in[mxn*4];char ch[mxn];
    void add(int x,int y){e[++cnt].to=y;e[cnt].lt=in[x];in[x]=cnt;}
    int id(char c){return c-'a';}
    void insert(int c)
    {
    	int p=lt,np=lt=++poi; t[np].len=t[p].len+1; t[np].sz=1;//因为每次新建的长度为i的点一定是独立的叶子节点
    	for(;p&&!t[p].ch[c];p=t[p].fa) t[p].ch[c]=np;//找到一个连接它的
    	if(!p){t[np].fa=rt;return;}//没有的话直接连向根
    	int q=t[p].ch[c];//找到了
    	if(t[q].len==t[p].len+1){t[np].fa=q;return;}//存在一个节点长度合适
    	int nq=++poi;t[nq].len=t[p].len+1;//复刻节点 然后原来的接在复刻的上面
    	memcpy(t[nq].ch,t[q].ch,sizeof(t[nq].ch));//原本的连接也需要复刻
    	t[nq].fa=t[q].fa;t[q].fa=t[np].fa=nq;//对于每一个节点连接到相应的父亲
    	for(;p&&t[p].ch[c]==q;p=t[p].fa)	t[p].ch[c]=nq;//修改本来连向原节点的
    }
    void build(){for(int i=2;i<=poi;i++)	add(t[i].fa,i);}//暴力连边
    int ans;
    void dfs(int x)//求值
    {
    	for(int i=in[x];i;i=e[i].lt){int y=e[i].to;dfs(y);t[x].sz+=t[y].sz;	}
    	if(t[x].sz!=1)	ans=max(ans,t[x].sz*t[x].len);
    }
    int main()
    {
    	scanf("%s",ch+1);
    	int len=strlen(ch+1);rt=lt=++poi;
    	for(int i=1;i<=len;i++)	insert(id(ch[i]));
    	build();dfs(rt);printf("%d
    ",ans);
    	return 0;
    }
  • 相关阅读:
    golang 数据结构 优先队列(堆)
    leetcode刷题笔记5210题 球会落何处
    leetcode刷题笔记5638题 吃苹果的最大数目
    leetcode刷题笔记5637题 判断字符串的两半是否相似
    剑指 Offer 28. 对称的二叉树
    剑指 Offer 27. 二叉树的镜像
    剑指 Offer 26. 树的子结构
    剑指 Offer 25. 合并两个排序的链表
    剑指 Offer 24. 反转链表
    剑指 Offer 22. 链表中倒数第k个节点
  • 原文地址:https://www.cnblogs.com/hanyuweining/p/10321920.html
Copyright © 2011-2022 走看看