Codeforces 159D Palindrome pairs


Description


You are given a non-empty string s consisting of lowercase letters. Find the number of pairs of non-overlapping palindromic substrings of this string.

In a more formal way, you have to find the quantity of tuples (a, b, x, y) such that 1 ≤ a ≤ b < x ≤ y ≤ |s| and substrings s[a... b], s[x... y] are palindromes.

A palindrome is a string that can be read the same way from left to right and from right to left. For example, "abacaba", "z", "abba" are palindromes.

A substrings[i... j] (1 ≤ i ≤ j ≤ |s|) of string s = s1s2... s|s| is a string sisi + 1... sj. For example, substring s[2...4] of string s = "abacaba" equals "bac".


Input


The first line of input contains a non-empty string s which consists of lowercase letters ('a'...'z'), s contains at most 2000 characters.


Output


Output a single number — the quantity of pairs of non-overlapping palindromic substrings of s.

Please do not use the %lld format specifier to read or write 64-bit integers in С++. It is preferred to use cin, cout streams or the %I64d format specifier.


Sample Input



Input
aa



Output
1



Input
aaa



Output
5



Input
abacaba



Output
36

题目大意:找出a,b;x,y回文串对数

两个dp数组 l[i]表示以第i个字母开头的回文串的个数(在整个串中)

r[i]表示以第i个字母结尾的回文串的个数(整个串中)

然后预处理 搜索一遍整个串 对每个i 用a,b枚举出以i为中心 或者结尾的回文 自然l[a]++,r[b]++

然后最后利用 前缀和,求出r[i]的前缀和,然后再次遍历str,

在第i个位置的时候,ans += l[i] * r[i-1];

这样,因为r是前缀和,所以就找出了所有的和以第i个字母开始成对的子回文串

代码如下:

//
// Create by Running Photon on 2015-03-12
//

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <cstdlib>
#include <iomanip>
#include <algorithm>
#include <cctype>
#include <stack>
#include <queue>
#include <map>
#include <string>
#include <set>
#include <vector>
using namespace std;

#define CLR(x) memset(x,0,sizeof x)
#define ll long long
const int inf=0x3f3f3f3f;
const int maxn=2e3+5;
const int MOD=5e5+5;
char str[maxn];
int l[maxn], r[maxn];
//l[i]表示以i开头的回文串的个数
//r[i]表示以i结尾的回文串的个数
//然后ans就是扫一遍,分别找到i之前回文串与i之后的回文串,乘起来,就是答案
int len;
int main()
{
#ifdef LOCAL
 freopen("in.txt","r",stdin);
 //freopen("out.txt","w",stdout);
#endif
 ios_base::sync_with_stdio(0);

 while(scanf("%s", str) != EOF){
        len = strlen(str);
        CLR(l),CLR(r);
        ll ans = 0;
        for(int i = 0; i < len; i++){
            for(int a = i, b = i+1; a >= 0 && b < len && str[a] == str[b]; a--, b++){//偶数回文
                l[a]++;
                r[b]++;
            }
            for(int a = i, b = i; a >= 0 && b < len && str[a] == str[b]; a--, b++){
                l[a]++;
                r[b]++;
            }
        }
        for(int i = 1; i < len; i++) r[i] += r[i-1];
        for(int i = 0; i < len; i++) ans += r[i] * l[i+1];
        printf("%I64d\n", ans);
 }

 return 0;
}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值