84pts 的暴力,但只有 60
查看原帖
84pts 的暴力,但只有 60
554145
Night_sea_64楼主2024/7/20 21:17

我的思路就是先枚举哪一段是 CC,然后 hash 判前面循环节。但是只有 60。

#include<iostream>
#include<cstring>
#include<algorithm>
using namespace std;
int t,n,c[26],cnt,sum[1100010][27];
long long ans;
string s;
const unsigned long long base=130;
unsigned long long h[1100010],power[1100010];
unsigned long long hs(int l,int r){
	return h[r]-h[l-1]*power[r-l+1];
}
void pre()
{
	for(int i=1;i<=n;i++)
		h[i]=h[i-1]*base+s[i];
	for(int i=1;i<=n;i++)
	{
		int x=s[i]-'a';
		c[x]++;
		if(c[x]%2)cnt++;
		else cnt--;
		for(int j=0;j<=26;j++)
			sum[i][j]=sum[i-1][j]+(cnt==j);
	}
	for(int i=1;i<=n;i++)
		for(int j=1;j<=26;j++)
			sum[i][j]+=sum[i][j-1];
}
bool chk(int x,int len){
	return hs(1,x-len)==hs(len+1,x);
}
int main()
{
	cin>>t;
	power[0]=1;
	for(int i=1;i<=1100000;i++)power[i]=power[i-1]*base;
	while(t--)
	{
		memset(c,0,sizeof(c));
		memset(sum,0,sizeof(sum));
		cnt=0;
		cin>>s;
		n=s.size();
		s=' '+s;
		pre();
		// for(int i=1;i<=n;i++)
		// {
		// 	for(int j=0;j<=4;j++)cout<<sum[i][j]<<" ";cout<<endl;
		// }
		memset(c,0,sizeof(c));
		cnt=0,ans=0;
		for(int i=n;i>=3;i--)
		{
			int x=s[i]-'a';
			c[x]++;
			if(c[x]%2)cnt++;
			else cnt--;
			for(int len=1;len*len<i;len++)
				if((i-1)%len==0)
				{
					if(chk(i-1,len))
					{
						//cout<<i-1<<" "<<len<<" "<<sum[len-1][cnt]<<endl;
						ans+=sum[len-1][cnt];
					}
					if(len*len<i-1&&chk(i-1,(i-1)/len))
					{
						//cout<<i-1<<" "<<(i-1)/len<<" "<<sum[(i-1)/len-1][cnt]<<endl;
						ans+=sum[(i-1)/len-1][cnt];
					}
				}
		}
		cout<<ans<<endl;
	}
	return 0;
}
2024/7/20 21:17
加载中...