zoukankan      html  css  js  c++  java
  • 【文文殿下】 [SDOI2016]生成魔咒

    字符集大小为1e9.............使用 map 吧

    统计本质不同的子串个数是SAM的经典应用之一

    本质不同的子串个数其实就是(sum max(x)-min(x)+1)

    所以我们新建结点 (np) 时统计它的答案即可

    根据我们统计的式子,显然新建节点(nq)的时候,不会对答案造成影响。

    #include<cstdio>
    #include<cstring>
    #include<map>
    typedef long long ll;
    const int maxn = 2e5+20;
    int par[maxn],mx[maxn],tr[maxn][26],Right[maxn],c[maxn],id[maxn];
    char A[maxn>>1];
    int tot=0;
    std::map<int,int> M;
    int cnt = 1,last = 1;
    ll ans = 0;
    void extend(int x) {
    	int np = ++cnt,p = last;
    	Right[np]=1;
    	mx[np]=mx[p]+1;
    	last=np;
    	while(p&&!tr[p][x]) tr[p][x]=np,p=par[p];
    	if(!p) par[np]=1;
    	else {
    		int q = tr[p][x];
    		if(mx[q]==mx[p]+1) {
    			par[np]=q;
    		}
    		else {
    			int nq = ++cnt;
    			mx[nq]=mx[p]+1;
    			memcpy(tr[nq],tr[q],sizeof tr[nq]);
    			par[nq]=par[q];
    			par[q]=par[np]=nq;
    			while(p&&tr[p][x]==q) tr[p][x]=nq,p=par[p];
    		}
    	}
    	ans+=mx[np]-mx[par[np]];
    	return;
    }
    int n,k,t;
    inline void topsort() {
    	for(int i = 1;i<=cnt;++i) ++c[mx[i]];
    	for(int i = 1;i<=n;++i) mx[i]+=mx[i-1];
    	for(int i = 1;i<=cnt;++i) id[c[mx[i]]--]=i;
    	for(int i = cnt;i;--i) Right[par[id[i]]]+=Right[id[i]];
    	return;
    }
    int ch;
    int main() {
    	scanf("%d",&n);
    	for(int i = 1;i<=n;++i) {
    		scanf("%d",&ch);
    		if(M[ch]==0) {
    			M[ch]=++tot;
    		}
    		extend(M[ch]);
    		printf("%lld
    ",ans);
    	}
    	return 0;
    }
    
    
  • 相关阅读:
    秋意浓浓回成都2月杂记
    验证表单的js代码段
    C#算法小程序(1)
    C#数据结构之单向链表
    Excel VBA编程的常用代码
    我的漫漫系分路
    2007年下半年系统分析师上午试卷及参考答案
    「2014年間休日カレンダー」のご案内
    Eclipse的几点使用技巧
    沧海一粟小组(第一次作业)
  • 原文地址:https://www.cnblogs.com/Syameimaru/p/9998924.html
Copyright © 2011-2022 走看看