【NOI2016】优秀的拆分(95分)

uoj 传送门

题目大意:给出一串字符串,求它的子串中形如AABB的方案个数。

90% len<=2000 ,O(n^2) 的做法可以过。
100% len<=30000, 蒟蒻不会啦。

O(n^2)的做法:
枚举中间点,求出两边形如AA的个数,相乘加入答案中。

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<string>
#include<cstring> 
#define LL long long
#define MOD 1000000009
#define base 163
#define M 30009
using namespace std;
int T,len;
LL Hash[M],P[M],ans;
char a[2009];
LL get_hash(int L,int R)
{
    return (Hash[R]-Hash[L-1]*P[R-L+1]%MOD+MOD)%MOD;
}
int main()
{
    P[0]=1;
    for(int i=1;i<=2001;i++) P[i]=P[i-1]*base%MOD;
    scanf("%d",&T);
    while(T--)
    {
        //gets(a+1);
        cin>>a+1;
        len=strlen(a+1);
        for(int i=1;i<=len;i++) Hash[i]=(Hash[i-1]*base+a[i]-'a')%MOD;

        ans=0;
        for(int i=2;i<=len-1;i++)
        {
            int L=0,R=0;
            for(int j=i/2;j;j--)
            {
                if(get_hash(i-j+1,i)==get_hash(i-2*j+1,i-j)) L++;
            }
            for(int j=(len-i)/2;j;j--)
            {
                if(get_hash(i+1,i+j)==get_hash(i+j+1,i+2*j)) R++;
            }
            ans+=L*R;
        }
        printf("%lld
",ans);
    }
    return 0;
}
原文地址:https://www.cnblogs.com/dfsac/p/7587827.html