zoukankan      html  css  js  c++  java
  • HDU-5785 Interesting(Manacher算法+区间处理)

    题目大意:给一个字符串,求所有相邻两回文子串的外侧下标之积的和

    题目分析:另L[i]为所有以 i 为右端点的回文字串的左端点之和,同理,另R[i]表示所有以 i 为左端点的回文子串的右端点之和。显然,答案为sigma(L[i]*R[i+1]) 其中,1<=i<length(字符串)。求出L和R是关键。先用manacher算法处理出p数组,然后再求出L和R。求L和R的思想(非常巧妙)跟树状数组求区间和的思想差不多。不过,这道题如果用树状数组或线段树的话会超时。

    参考代码:

    # include<iostream>
    # include<cstdio>
    # include<cstring>
    # include<algorithm>
    using namespace std;
    # define LL long long
    
    const int mod=1000000007;
    const int N=1000000;
    
    char str[N+5];
    char m[(N<<1)+5];
    int p[(N<<1)+5];
    
    LL addtag[2][N+5];
    LL subtag[2][N+5];
    LL addcnt[2][N+5];
    LL subcnt[2][N+5];
    LL val[2][N+5];
    
    void manacher(char *ch)
    {
    	int len=strlen(ch+1);
    	int cnt=0;
    	m[cnt++]='@';
    	m[cnt++]='#';
    	for(int i=1;i<=len;++i){
    		m[cnt++]=ch[i];
    		m[cnt++]='#';
    	}
    	m[cnt]='';
    	int id,mx=0;
    	for(int i=1;i<cnt;++i){
    		if(mx>i) p[i]=min(mx-i,p[2*id-i]);
    		else p[i]=1;
    		while(m[i-p[i]]==m[i+p[i]]) ++p[i];
    		if(i+p[i]>mx){
    			mx=i+p[i];
    			id=i;
    		}
    	}
    }
    
    void update(int id,int l,int r,int a)
    {
    	addtag[id][l]+=a;
    	addtag[id][l]%=mod;
    	++addcnt[id][l];
    	subtag[id][r+1]+=a-r+l;
    	subtag[id][r+1]%=mod;
    	++subcnt[id][r];
    }
    
    void pushDown(int n)
    {
    	for(int i=1;i<=n;++i){
    		if(addcnt[0][i]){
    			val[0][i]+=addtag[0][i];
    			val[0][i]%=mod;
    			addtag[0][i+1]+=addtag[0][i]-addcnt[0][i];
    			addtag[0][i+1]%=mod;
    			addcnt[0][i+1]+=addcnt[0][i];
    		}
    		if(subcnt[0][i]){
    			val[0][i]-=subtag[0][i];
    			val[0][i]%=mod;
    			subtag[0][i+1]+=subtag[0][i]-subcnt[0][i];
    			subtag[0][i+1]%=mod;
    			subcnt[0][i+1]+=subcnt[0][i];
    		}
    		if(addcnt[1][i]){
    			val[1][i]+=addtag[1][i];
    			val[1][i]%=mod;
    			addtag[1][i+1]+=addtag[1][i]-addcnt[1][i];
    			addtag[1][i+1]%=mod;
    			addcnt[1][i+1]+=addcnt[1][i];
    		}
    		if(subcnt[1][i]){
    			val[1][i]-=subtag[1][i];
    			val[1][i]%=mod;
    			subtag[1][i+1]+=subtag[1][i]-subcnt[1][i];
    			subtag[1][i+1]%=mod;
    			subcnt[1][i+1]+=subcnt[1][i];
    		}
    	}
    }
    
    int main()
    {
    	while(~scanf("%s",str+1))
    	{
    		manacher(str);
    		memset(val,0,sizeof(val));
    		memset(addtag,0,sizeof(addtag));
    		memset(subtag,0,sizeof(subtag));
    		memset(addcnt,0,sizeof(addcnt));
    		memset(subcnt,0,sizeof(subcnt));
    		for(int i=1;m[i];++i){
    			if(i&1){
    				if(p[i]==1) continue;
    				update(0,i/2+1,i/2+p[i]/2,i/2);
    				update(1,i/2-p[i]/2+1,i/2,i/2+p[i]/2);
    			}else{
    				int id=i/2;
    				int l=(p[i]-1)/2;
    				update(0,id,id+l,id);
    				update(1,id-l,id,id+l);
    			}
    		}
    		int n=strlen(str+1);
    		pushDown(n);
    		LL ans=0;
    		for(int i=1;i<n;++i){
    			ans+=val[0][i]*val[1][i+1];
    			ans%=mod;
    		}
    		while(ans<0) ans+=mod;
    		printf("%lld
    ",ans);
    	}
    	return 0;
    }
    

      

  • 相关阅读:
    linux 环境变量 ($PATH)
    read()、write()返回 Input/output error, Device or resource busy解决
    初次尝试一个注册表
    CSS定位
    CSS中颜色代码和单位
    DOM和BOM
    java代码中获取classpath路径
    黑盒测试与白盒测试相比,哪个更难
    LoadRunner11遇到问题及解决办法
    Linux下修改日期和时间
  • 原文地址:https://www.cnblogs.com/20143605--pcx/p/5743439.html
Copyright © 2011-2022 走看看