zoukankan      html  css  js  c++  java
  • P3181 [HAOI2016]找相同字符

    P3181 [HAOI2016]找相同字符

    对一个串建SAM,另一个串在这上面跑,到达一点时,假设经过了(cnt)个点
    计算这个串所有后缀产生的贡献就好了,直接暴力跑上去可能会超时,topsort预处理一下

    #include<iostream>
    #include<cstdio>
    #include<cstdlib>
    #include<cstring>
    #include<cmath>
    #include<algorithm>
    #include<set>
    #include<map>
    #include<vector>
    #include<queue>
    using namespace std;
    typedef long long LL;
    const LL maxn=500000;
    LL nod,last,n,T;
    LL len[maxn],fail[maxn],son[maxn][26],Ans[maxn],sum[maxn],c[maxn],p[maxn],size[maxn],fval[maxn];
    char s[maxn];
    inline void Insert(LL c){
    	LL np=++nod,p=last;
    	len[np]=len[p]+1;
    	last=np;
    	while(p&&!son[p][c]){
    		son[p][c]=np,
    		p=fail[p];
    	}
    	if(!p)
    	    fail[np]=1;
    	else{
    		LL q=son[p][c];
    		if(len[q]==len[p]+1)
    		    fail[np]=q;
    		else{
    			LL nq=++nod;
    			len[nq]=len[p]+1;
    			fail[nq]=fail[q];
    			memcpy(son[nq],son[q],sizeof(son[q]));
    			fail[np]=fail[q]=nq;
    			while(p&&son[p][c]==q){
    				son[p][c]=nq,
    				p=fail[p];
    			}
    		}
    	}
    	size[last]=1;
    }
    int main(){	
    	nod=last=1;
    	scanf("%s",s);
    	LL Len=strlen(s);
    	for(LL i=0;i<Len;++i)
    		Insert(s[i]-'a');
    		
    	for(LL i=1;i<=nod;++i)
    	    c[len[i]]++;
        for(LL i=1;i<=nod;++i)
    	    c[i]+=c[i-1];
        for(LL i=1;i<=nod;++i)
    	    p[c[len[i]]--]=i;
    	for(LL i=nod;i>=1;--i)
            size[fail[p[i]]]+=size[p[i]];
        for(LL i=1;i<=nod;i++)
    	    fval[p[i]]=(len[p[i]]-len[fail[p[i]]])*size[p[i]]+fval[fail[p[i]]];
            
    	scanf("%s",s);
    	LL now=1,cnt=0,ans=0;
    	Len=strlen(s);
    	for(LL i=0;i<Len;++i){
    		LL c=s[i]-'a';
    		if(son[now][c])
    		    ++cnt,
    		    now=son[now][c];
    		else{
    			while(now&&!son[now][c])
    			    now=fail[now];
    			if(!now)
    				cnt=0,
    			    now=1;
    			else
    			    cnt=len[now]+1,
    			    now=son[now][c];
    		}
    		if(now!=1)
    		    ans+=fval[fail[now]]+(cnt-len[fail[now]])*size[now];
    	}
    	printf("%lld",ans);
    	return 0;
    }/*
    fjewiofejhiofjmwopejeugfzjkjnfoakweldnfmoierhguiewkjfkowejrfoiwejsfd
    jwierhdwuiek,dedjfkz[pjeowrfhuqigrfwerljfiuekdfkcdfheosf
    */
    
  • 相关阅读:
    背景样式、列表样式、变形样式、过渡动画
    边框样式、段落样式、背景样式
    属性选择符、字体样式和元素样式
    Targets选项下Other linker flags的设置
    OC金额转大写
    输入手机号码 和 金额有效性的判断
    iOS手势冲突问题
    解决iOS手势冲突问题
    iOS开发 字符串的转化 小技巧
    iOS开发添加pch文件
  • 原文地址:https://www.cnblogs.com/y2823774827y/p/10202242.html
Copyright © 2011-2022 走看看