一道noip C++ 的题~~求写注释看不懂 100
题目:Task3.回文串计数(calc.pas/calc.c/calc.cpp)【题目描述】虽然是一名理科生,Mcx常常声称自己是一名真正的文科生。不知为何,他对于背诵总...
题目:
Task 3.回文串计数(calc.pas/calc.c/calc.cpp)
【题目描述】
虽然是一名理科生,Mcx常常声称自己是一名真正的文科生。不知为何,他对于背诵总有一种莫名的热爱,这也促使他走向了以记忆量大而闻名的生物竞赛。然而,他很快发现这并不能满足他热爱背诵的心,但是作为一名强大的Boer,他找到了这么一条自虐的方式——背诵基因序列。不过这实在是太虐心了,就连Mcx也有些招架不住。不过他发现,如果他能事先知道这个序列里有多少对互不相交的回文串,他或许可以找到记忆的妙法。为了进一步验证这个方法,Mcx决定选取一个由小写字母构成的字符串SS来实验。不过由于互不相交的回文串实在过多,他很快就数晕了。不过他相信,在你的面前这个问题不过是小菜一碟。
【名词解释】
1.对于字符串SS,设其长度为Len,那么下文用Si表示SS中第i个字符(1<=i<=Len)
2.s[i,j]表示SS的一个字串,s[i,j] = “SiSi+1Si+2…Sj-2Sj-1Sj”,比如当SS为”abcgfd”时,
s[2,5] = “bcgf” , s[1,5] = “abcgf”
3.当一个串被称为一个回文串当且仅当将这个串反写后与原串相同,如”abcba”
4.考虑一个四元组(l,r,L,R) , 当s[l,r]和s[L,R]均为回文串时,且满足1 <= l <=r<L <= R <= Len时,我们称s[l,r]和s[L,R]为一对互不相交的回文串。也即本题所求即为这种四元组的个数。两个四元组相同当且仅当对应的l,r,L,R都相同。
【题目输入】
仅一行,为字符串SS,保证全部由小写字母构成,由换行符标志结束。
【题目输出】
仅一行,为一个整数,表示互不相交的回文串的对数。
【样例输入】
aaa
【样例输出】
5
【样例解释】
SS= “aaa” , SS的任意一个字串均为回文串,其中总计有5对互不相交的回文串:
(1,1,2,2) , (1,1,2,3) , (1,1,3,3) ,(1,2,3,3) , (2,2,3,3). (这里使用名词解释中的四元组进行表示)
【数据范围】
50%的数据满足SS的长度不超过200
100%的数据满足SS的长度不超过2000
标程:
#include"cstdio"
#include"cstdlib"
#include"cstring"
#include"cmath"
#include"algorithm"
#include"vector"
#include"set"
#include"iostream"
#include"map"
using namespace std;
const int N = 2010 , mod = 10017;
int h[2][N] , mi[N] , len;
char str[2][N];
inline int Hash(int s , int t , int k)
{
return h[k][t] - h[k][s - 1] * mi[t - s + 1];
}
long long Count(int s , int t , int k)
{
int l = t - s + 1 , ans = 0;
for(int length = 1 ; length <= l ; length++)
{
int s1 = t - length + 1 , t1 = t - length + (length + 1) / 2;
int s2 = len + 1 - t , t2 = len - t + (length + 1) / 2;
ans += Hash(s1 , t1 , k) == Hash(s2 , t2 , k);
}
return ans;
}
int main()
{
freopen("calc.in","r",stdin);
freopen("calc.out","w",stdout);
scanf("%s\n",str[0]);
len=strlen(str[0]);
for(int i=0,j=len-1;i<len;j--,i++)
str[1][i]=str[0][j];
mi[0]=1;
h[0][1]=str[0][0]-'a';
h[1][1]=str[1][0]-'a';
for(int i=1;i<=len;i++)
{
mi[i]=mi[i-1]*mod;
h[0][i+1]=h[0][i]*mod+str[0][i]-'a';
h[1][i+1]=h[1][i]*mod+str[1][i]-'a';
}
long long ans=0,s=0;
for(int i=0;i<len-1;i++)
{
s+=Count(1,i+1,0);
ans+=s*Count(1,len-i-1,1);
}
cout << ans << endl;
fclose(stdin);
fclose(stdout);
return 0;
} 展开
Task 3.回文串计数(calc.pas/calc.c/calc.cpp)
【题目描述】
虽然是一名理科生,Mcx常常声称自己是一名真正的文科生。不知为何,他对于背诵总有一种莫名的热爱,这也促使他走向了以记忆量大而闻名的生物竞赛。然而,他很快发现这并不能满足他热爱背诵的心,但是作为一名强大的Boer,他找到了这么一条自虐的方式——背诵基因序列。不过这实在是太虐心了,就连Mcx也有些招架不住。不过他发现,如果他能事先知道这个序列里有多少对互不相交的回文串,他或许可以找到记忆的妙法。为了进一步验证这个方法,Mcx决定选取一个由小写字母构成的字符串SS来实验。不过由于互不相交的回文串实在过多,他很快就数晕了。不过他相信,在你的面前这个问题不过是小菜一碟。
【名词解释】
1.对于字符串SS,设其长度为Len,那么下文用Si表示SS中第i个字符(1<=i<=Len)
2.s[i,j]表示SS的一个字串,s[i,j] = “SiSi+1Si+2…Sj-2Sj-1Sj”,比如当SS为”abcgfd”时,
s[2,5] = “bcgf” , s[1,5] = “abcgf”
3.当一个串被称为一个回文串当且仅当将这个串反写后与原串相同,如”abcba”
4.考虑一个四元组(l,r,L,R) , 当s[l,r]和s[L,R]均为回文串时,且满足1 <= l <=r<L <= R <= Len时,我们称s[l,r]和s[L,R]为一对互不相交的回文串。也即本题所求即为这种四元组的个数。两个四元组相同当且仅当对应的l,r,L,R都相同。
【题目输入】
仅一行,为字符串SS,保证全部由小写字母构成,由换行符标志结束。
【题目输出】
仅一行,为一个整数,表示互不相交的回文串的对数。
【样例输入】
aaa
【样例输出】
5
【样例解释】
SS= “aaa” , SS的任意一个字串均为回文串,其中总计有5对互不相交的回文串:
(1,1,2,2) , (1,1,2,3) , (1,1,3,3) ,(1,2,3,3) , (2,2,3,3). (这里使用名词解释中的四元组进行表示)
【数据范围】
50%的数据满足SS的长度不超过200
100%的数据满足SS的长度不超过2000
标程:
#include"cstdio"
#include"cstdlib"
#include"cstring"
#include"cmath"
#include"algorithm"
#include"vector"
#include"set"
#include"iostream"
#include"map"
using namespace std;
const int N = 2010 , mod = 10017;
int h[2][N] , mi[N] , len;
char str[2][N];
inline int Hash(int s , int t , int k)
{
return h[k][t] - h[k][s - 1] * mi[t - s + 1];
}
long long Count(int s , int t , int k)
{
int l = t - s + 1 , ans = 0;
for(int length = 1 ; length <= l ; length++)
{
int s1 = t - length + 1 , t1 = t - length + (length + 1) / 2;
int s2 = len + 1 - t , t2 = len - t + (length + 1) / 2;
ans += Hash(s1 , t1 , k) == Hash(s2 , t2 , k);
}
return ans;
}
int main()
{
freopen("calc.in","r",stdin);
freopen("calc.out","w",stdout);
scanf("%s\n",str[0]);
len=strlen(str[0]);
for(int i=0,j=len-1;i<len;j--,i++)
str[1][i]=str[0][j];
mi[0]=1;
h[0][1]=str[0][0]-'a';
h[1][1]=str[1][0]-'a';
for(int i=1;i<=len;i++)
{
mi[i]=mi[i-1]*mod;
h[0][i+1]=h[0][i]*mod+str[0][i]-'a';
h[1][i+1]=h[1][i]*mod+str[1][i]-'a';
}
long long ans=0,s=0;
for(int i=0;i<len-1;i++)
{
s+=Count(1,i+1,0);
ans+=s*Count(1,len-i-1,1);
}
cout << ans << endl;
fclose(stdin);
fclose(stdout);
return 0;
} 展开
2个回答
推荐律师服务:
若未解决您的问题,请您详细描述您的问题,通过百度律临进行免费专业咨询