zoukankan      html  css  js  c++  java
  • CF17E Palisection(manacher/回文树)

    CF17E Palisection(manacher/回文树)

    Luogu

    题解时间

    直接正难则反改成求不相交的对数。

    manacher求出半径之后就可以差分搞出以某个位置为开头/结尾的回文串个数。

    然后就容易求出不相交的对数,用总数减去即为答案。

    啊是的这题好像也可以用回文树做。

    #include<bits/stdc++.h>
    using namespace std;
    namespace RKK
    {
    const int N=4000011,mo=51123987;
    void doadd(int &a,int b){if((a+=b)>=mo) a-=mo;}
    int add(int a,int b){return (a+=b)>=mo?a-mo:a;}
    
    int n,m;char s[N];
    
    int r[N],mar,mai;
    
    int tot,ls[N],rs[N];
    
    int main()
    {
    	scanf("%d%s",&n,s+1);
    	s[0]='@';for(int i=n;i;i--)s[i<<1]=s[i],s[(i<<1)-1]='#';s[n<<1|1]='#';m=n<<1|1;
    	for(int i=1;i<=m;i++)
    	{
    		r[i]=i<=mar?min(r[(mai<<1)-i],mar-i+1):1;
    		while(s[i-r[i]]==s[i+r[i]]) r[i]++;
    		if(i+r[i]>mar) mar=i+r[i]-1,mai=i;
    		doadd(tot,r[i]>>1),ls[i-r[i]+1]++,ls[i+1]--,rs[i]++,rs[i+r[i]]--;
    	}
    	for(int i=1;i<=m;i++) doadd(ls[i],ls[i-1]),doadd(rs[i],rs[i-1]);
    	tot=1ll*tot*(tot-1)/2%mo; 
    	for(int i=1,s=0;i<=n;i++) doadd(tot,mo-1ll*s*ls[i<<1]%mo),doadd(s,rs[i<<1]);
    	printf("%d
    ",tot);
    	return 0;
    }
    }
    int main(){return RKK::main();}
    
  • 相关阅读:
    P4297 [NOI2006]网络收费
    P4207 [NOI2005]月下柠檬树
    bzoj2517 矩形覆盖
    bzoj2506 calc
    ......
    SP1811 LCS
    CF585E Present for Vitalik the Philatelist
    好康的
    CF605E Intergalaxy Trips
    字符串
  • 原文地址:https://www.cnblogs.com/rikurika/p/12846187.html
Copyright © 2011-2022 走看看