.第二饭堂 (hw.pas/c/cpp)
问题描述
由于一饭班长表示各种鸭梨,美丽的*中决定历史性地启用第二饭堂。
而部分领导觉得,二饭依山傍水,环境优美,未免有不和谐的事情(你懂的)发生,决定到二饭巡视同学们用餐时的就座情况。
为了应付这一情况,同学们决定联合起来“布阵”。 方便起见,同学们已经把座位情况抽象成一个长度为n的仅含数字及字母的字符串,他们想请你帮忙算算这个字符串的和谐程度。
已知一个字符串被称为k-回文串的充要条件是它自身是回文串,并且它长为⌊n/2⌋(下取整)的前缀和后缀是(k-1)-回文串。根据定义,任意字符串(包括空串)都是0-回文串。
一个字符串的回文度数就是这个字符串的k的最大值。
问题描述
由于一饭班长表示各种鸭梨,美丽的*中决定历史性地启用第二饭堂。
而部分领导觉得,二饭依山傍水,环境优美,未免有不和谐的事情(你懂的)发生,决定到二饭巡视同学们用餐时的就座情况。
为了应付这一情况,同学们决定联合起来“布阵”。 方便起见,同学们已经把座位情况抽象成一个长度为n的仅含数字及字母的字符串,他们想请你帮忙算算这个字符串的和谐程度。
已知一个字符串被称为k-回文串的充要条件是它自身是回文串,并且它长为⌊n/2⌋(下取整)的前缀和后缀是(k-1)-回文串。根据定义,任意字符串(包括空串)都是0-回文串。
一个字符串的回文度数就是这个字符串的k的最大值。
而对于一个给定的字符串,它的和谐程度就是其所有前缀的回文度数之和。 你的任务就是算出这个和谐程度具体是多少。
输入
一行一个仅包含数字和字母的字符串。
输出
一行一个整数表示这个字符串的和谐高度。
输入输出样例
hw.in
abacaba
hw.out
6
数据规模
对于30%的数据字符串长度不超过1000
对于70%的数据字符串长度不超过100000
对于100%的数据字符串长度不超过5000000
首先关于和谐程度,是一个递推关系:F(x)=F(x/2)+1
但是这题一看数据就非常大,然后我还是义无反顾的暴搜了
#include<cstdio>
#include<cstdlib>
#include<cstring>
int a[5000001],h[5000001],n,l,ans;
char s[5000001];
int main()
{
int i,j;
void hw(int m);
int check(int m);
freopen("hw.in","r",stdin);
freopen("hw.out","w",stdout);
gets(s);
n=strlen(s);
h[1]=1;
ans=1;
for(i=1;i<=n;i++)a[i]=s[i-1];
for(i=2;i<=n;i++)hw(i);
for(i=2;i<=n;i++)ans=ans+h[i];
printf("%d\n",ans);
fclose(stdin);
fclose(stdout);
return 0;
}
int check(int m)
{
int p,q,f;
p=1;q=m;f=1;
while(p<=q)
{
if(a[p]!=a[q])f=0;
p++;q--;
}
return f;
}
void hw(int m)
{
if (check(m)==0)h[m]=0;
else h[m]=h[m/2]+1;
}
这样的话可以过七个点,主要时间是花在判断回文上。如何才能更有效更快的判断回文?
#include <iostream>
#include <cstdio>
using namespace std;
char s[5000010];
int f[5000010];
int main(){
freopen("hw.in","r",stdin);
freopen("hw.out","w",stdout);
scanf("%s", s);
int l=0, r=0, e=1, ans=0;
for (int i=0; s[i]; i++){
l=l*107+s[i];
r=r+s[i]*e; e*=107;
if (l==r) f[i+1]=f[(i+1)/2]+1;
ans+=f[i+1];
}
cout<<ans<<endl;
return 0;
}
对于每一个回文计算一个哈希值