• luogu P4070 [SDOI2016]生成魔咒


    首先有两个结论:
    1.后缀自动机具有最简性,即每种不同的子串只会在sam上体现一次,体现形式是sam上一条由root出发的路径。
    2.一个字符串不同子串的个数等于所有关键节点的max(x)-min(x)+1。证明就是考虑后缀自动机的最简性。

    然后,这就是个水题了。
    每次插入一个字符后,更新答案即可。

    #include<iostream>
    #include<cctype>
    #include<cstdio>
    #include<cstring>
    #include<string>
    #include<cmath>
    #include<ctime>
    #include<map>
    #include<cstdlib>
    #include<algorithm>
    #define N 330000
    #define L 300000
    #define eps 1e-7
    #define inf 1e9+7
    #define ll long long
    using namespace std;
    inline int read()
    {
    	char ch=0;
    	int x=0,flag=1;
    	while(!isdigit(ch)){ch=getchar();if(ch=='-')flag=-1;}
    	while(isdigit(ch)){x=(x<<3)+(x<<1)+ch-'0';ch=getchar();}
    	return x*flag;
    }
    char ch[N];
    bool flag[N];
    int root=1,size=1,last=1,id[N];
    struct node{int len,link;map<int,int>nxt;}s[N];
    void insert(int k)
    {
    	int cur=++size,p=last;
    	s[cur].len=s[p].len+1;
    	while(p&&!s[p].nxt[k])
    	{
    		s[p].nxt[k]=cur;
    		p=s[p].link;
    	}
    	last=cur;
    	if(!p){s[cur].link=root;return;}
    	int q=s[p].nxt[k];
    	if(s[q].len==s[p].len+1)s[cur].link=q;
    	else
    	{
    		int clone=++size;
    		s[clone]=s[q];
    		s[clone].len=s[p].len+1;
    		while(p&&s[p].nxt[k]==q)
    		{
    			s[p].nxt[k]=clone;
    			p=s[p].link;
    		}
    		s[q].link=s[cur].link=clone;
    	}
    }
    int main()
    {
    	ll ans=0;
    	int n=read();
    	for(int i=1;i<=n;i++)
    	{
    		int x=read();
    		insert(x);
    		ans+=s[last].len-s[s[last].link].len;
    		printf("%lld
    ",ans);
    	}
    	return 0;
    }
    
  • 相关阅读:
    c++ 内存管理
    socket粘包现象加解决办法
    TCP与UDP比较 以及并发编程基础知识
    进程之 Process join方法其他属性与进程Queue
    socket通讯实例与TCP/UDP的区别
    socket介绍
    python中的异常处理机制
    面向对象之多态,多态性,反射,以及基于反射的可拔插设计
    面向对象之元类介绍
    面向对象基础
  • 原文地址:https://www.cnblogs.com/Creed-qwq/p/10159601.html
Copyright © 2020-2023  润新知