http://codeforces.com/problemset/problem/159/D
题目大意:
给出一个字符串,求取这个字符串中互相不覆盖的两个回文子串的对数。
思路:num[i]代表左端点在i这个位置的回文串个数,然后用树状数组维护sum[i],代表回文串右端点小于等于i的回文串数,总复杂度:O(n^2)
1 #include<cstdio> 2 #include<cmath> 3 #include<algorithm> 4 #include<cstring> 5 #include<iostream> 6 #define ll long long 7 ll c[200005],num[200005]; 8 int pd[2005][2005],n; 9 char s[200005]; 10 int lowbit(int x){ 11 return x&(-x); 12 } 13 int read(){ 14 int t=0,f=1;char ch=getchar(); 15 while (ch<'0'||ch>'9'){if (ch=='-') f=-1;ch=getchar();} 16 while ('0'<=ch&&ch<='9'){t=t*10+ch-'0';ch=getchar();} 17 return t*f; 18 } 19 void add(int x){ 20 for (int i=x;i<=n;i+=lowbit(i)){ 21 c[i]++; 22 } 23 } 24 int ask(int x){ 25 int res=0; 26 for (int i=x;i;i-=lowbit(i)){ 27 res+=c[i]; 28 } 29 return res; 30 } 31 int main(){ 32 scanf("%s",s+1); 33 n=strlen(s+1); 34 for (int i=1;i<=n;i++) 35 pd[i][i]=1,add(i),num[i]++; 36 for (int i=1;i<n;i++) 37 if (s[i]==s[i+1]) pd[i][i+1]++,add(i+1),num[i]++; 38 for (int len=3;len<=n;len++) 39 for (int i=1;i+len-1<=n;i++){ 40 int j=i+len-1; 41 if (pd[i+1][j-1]&&s[i]==s[j]) pd[i][j]=1,add(j),num[i]++; 42 } 43 ll ans=0; 44 for (int i=1;i<=n;i++) 45 ans+=ask(i-1)*((ll)(num[i])); 46 printf("%I64d\n",ans); 47 return 0; 48 }