/*
分析:
(找规律+递推) && (线段树 || 树状数组),非区间dp方法。
以后都不准备再贴水题了,不过这题我比赛时想到的方法和解题报告的方法不一样,所
以贴下。。
1. 经过观察,发现性质:对于str[i]==str[j] && i<j,那么所有首位为a、末位为b、且满足
(i<a && a<=b && b<j)的回文序列,一定可以在两端加上str[i]和str[j]后,构成一个新的回
文序列,并且这个回文序列的首元素为str[i]、尾元素为str[j];
2. 维护两个数组,ans[N]和cnt[N],ans[i]表示以元素i为首位的回文序列的数量、cnt[i]表
示以元素i结尾的回文序列的数量;
3. 逆向遍历str(正向也行),初始化ans[i]=1,cnt[i]=1,代表自己单独为一个序列;同
时用指针j,从str尾向前遍历while(i<j),当str[i]==str[j]的时候,进行如下操作:
(1)ans[i]++,cnt[j]++,(代表i和j单独构成一个序列);
(2)统计sum=所有cnt[k]的和,k满足(i<k && k<j),然后ans[i]+=sum,cnt[i]+=sum;
最后统计所有的ans的SUM,既为所求。
对于3.(2),需要用树状数组或者线段树快速求和。
源自------------------------------------- Ice_Crazy
2013-08-02
*/
分析:
(找规律+递推) && (线段树 || 树状数组),非区间dp方法。
以后都不准备再贴水题了,不过这题我比赛时想到的方法和解题报告的方法不一样,所
以贴下。。
1. 经过观察,发现性质:对于str[i]==str[j] && i<j,那么所有首位为a、末位为b、且满足
(i<a && a<=b && b<j)的回文序列,一定可以在两端加上str[i]和str[j]后,构成一个新的回
文序列,并且这个回文序列的首元素为str[i]、尾元素为str[j];
2. 维护两个数组,ans[N]和cnt[N],ans[i]表示以元素i为首位的回文序列的数量、cnt[i]表
示以元素i结尾的回文序列的数量;
3. 逆向遍历str(正向也行),初始化ans[i]=1,cnt[i]=1,代表自己单独为一个序列;同
时用指针j,从str尾向前遍历while(i<j),当str[i]==str[j]的时候,进行如下操作:
(1)ans[i]++,cnt[j]++,(代表i和j单独构成一个序列);
(2)统计sum=所有cnt[k]的和,k满足(i<k && k<j),然后ans[i]+=sum,cnt[i]+=sum;
最后统计所有的ans的SUM,既为所求。
对于3.(2),需要用树状数组或者线段树快速求和。
源自------------------------------------- Ice_Crazy
2013-08-02
*/
#include"iostream"
#include"cstdio"
#include"cstring"
using namespace std;
const int N=1006;
const int mod=10007;
int n,lowbit[N];
__int64 C[N],ans[N];
char str[N];
void update(int k,int dir)
{
while(0<k && k<=n)
{
C[k]=(C[k]+dir)%mod;
k+=lowbit[k];
}
}
int sum(int k)
{
__int64 p=0;
while(0<k && k<=n)
{
p=(p+C[k])%mod;
k-=lowbit[k];
}
return p;
}
int main()
{
int T,Case;
int i,l;
__int64 a,b,t;
__int64 hehe;
for(i=1;i<=1000;i++) lowbit[i]=i&(-i);
cin>>T;
for(Case=1;Case<=T;Case++)
{
hehe=0;
scanf("%s",str+1);
memset(C,0,sizeof(C));
memset(ans,0,sizeof(ans));
for(n=1;str[n];n++);
n--;
for(i=n;i>=1;i--)
{
ans[i]=1;
update(i,1);
for(l=n;l>i;l--)
{
if(str[l]==str[i])
{
a=sum(i);
b=sum(l-1);
t=(b-a)%mod;
while(t<0) t+=mod;
ans[i]=(ans[i]+1+t)%mod;
update(l,1+t);
}
}
}
hehe=0;
for(i=1;i<=n;i++) hehe=(hehe+ans[i])%mod;
printf("Case %d: %I64d\n",Case,hehe);
}
return 0;
}