• 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;
    }
    
  • 相关阅读:
    文件上传Web小案例
    加密方法(MD5加密)
    解决中文乱码(不可能解决不了)
    jquery的一些常见使用方法
    Ajax的作用
    日期时间格式的转换
    前端点击复制内容
    uniapp 移动端防止点击事件穿透
    getCurrentPages 获取当前网页完整的URL
    关闭微信浏览器网页
  • 原文地址:https://www.cnblogs.com/Creed-qwq/p/10159601.html
Copyright © 2020-2023  润新知