题目描述

如果把一个字符串从头到尾翻转后和原字符串相等,我们称之为回文串,比如“aabaa”、“())(”、“2017102”。

如果一个字符串存在两个出现过的字母出现的次数相等,我们称之为好

的字符串。

现在给一个由小写字母组成的字符串,问在这个字符串的所有连续的串

中,好的回文串有多少个。(两个相同的回文串出现在不同位置算多次)。

输入输出格式

输入格式:

一行一个小写字母组成的字符串。

输出格式:

一行一个整数,表示答案。

输入输出样例

输入样例#1:

abcbaabcba
输出样例#1:

6
【样例解释】
abcba s[1..5] a,b 出现次数相等
baab s[4..7] a,b 出现次数相等
cbaabc s[3..8] a,b 出现次数相等
bcbaabcb s[2..9] a,c 出现次数相等
abcbaabcba s[1..10] a,b 出现次数相等
abcba s[6..10] a,b 出现次数相等

说明

len 表示字符串长度。

对于30% 的数据, len <=10^2。

对于60% 的数据, len <= 10^3。

对于100% 的数据,1 <= len <= 10^4。

 /*
我们发现回文串是可以二分的
比如:bbbabcbaabcba 我们以第1个c为中心,发现回文半径是3,大于3一定不是回文串。当回文串长度为偶数的时候,我们需要特殊处理一下。
现在有一个结论:本质不同的回文串个数只有O(N)个
本质不同:字符串本身是不同的。
每一次处理完回文串,我们要把他的hash值记录下来。
*/ #include<cstdio>
#include<cstring>
#include<algorithm>
#include<map>
using namespace std; typedef unsigned long long ULL;
typedef long long LL; char s[];
ULL h[],rh[],pw[];
int L; ULL hs(int l,int r)
{
return h[r]-h[l-]*pw[r-l+];
}
ULL rhs(int l,int r)
{
return rh[l]-rh[r+]*pw[r-l+];
}
struct N
{
int a[];
bool ok(){
int b[];
for(int i=;i<;i++) b[i]=a[i];
sort(b,b+);
for(int i=;i<;i++)
{
if(b[i]>&& b[i] == b[i+]) return true;
}
return false;
}
void clear()
{
memset(a,,sizeof a);
}
};
LL ans=;
map<ULL,LL> num;
map<ULL,N> A;
void solve_odd() //奇数
{
for(int i=;i<=L;i++)
{
int l=,r=min(i,L-i+)+;
while(r-l>)
{
int mid=(l+r)/;
if(hs(i-mid+,i+mid-)==rhs(i-mid+,i+mid-)) l=mid;
else r=mid;
}
int p=l;
int tmp=p;
while(tmp>=&&num.find(hs(i-tmp+,i+tmp-))==num.end()) tmp--;
LL sum=;
N st;
st.clear();
if(tmp>=)
{
sum=num[hs(i-tmp+,i+tmp-)];
st=A[hs(i-tmp+,i+tmp-)];
}
while(tmp<p)
{
st.a[s[i+tmp]-'a']+=(tmp==?:);
if(st.ok()) sum++;
num[hs(i-tmp,i+tmp)]=sum;
A[hs(i-tmp,i+tmp)]=st;
tmp++;
}
ans+=sum;
}
}
void solve_even() //偶数
{
A.clear();
num.clear();
for(int i=;i<L;i++)
{
int l=,r=min(i,L-i)+;
while(r-l>)
{
int mid=(l+r)/;
if(hs(i-mid+,i+mid)== rhs(i-mid+,i+mid)) l=mid;
else r=mid;
}
int p=l;
int tmp=p;
while(tmp>=&&num.find(hs(i-tmp+,i+tmp))==num.end()) tmp--;
LL sum = ;
N st;
st.clear();
if(tmp>=)
{
sum=num[hs(i-tmp+,i+tmp)];
st=A[hs(i-tmp+,i+tmp)];
}
while(tmp<p)
{
st.a[s[i+tmp+]-'a']+=;
if(st.ok()) sum++;
num[hs(i-tmp,i+tmp+)]=sum;
A[hs(i-tmp,i+tmp+)]=st;
tmp++;
}
ans+=sum;
}
} int main()
{
scanf("%s",s+);
L=strlen(s+);
s[]='#';
pw[]=;
for(int i=;i<=L;i++) pw[i]=pw[i-]*; ///hash值
for(int i=;i<=L;i++) h[i]=h[i-]*+s[i];
for(int i=L;i>=;i--) rh[i]=rh[i+]*+s[i];
solve_odd();
solve_even();
printf("%lld\n",ans);
fclose(stdout);
return ;
}

2017.10.6 国庆清北 D6T3 字符串的更多相关文章

  1. 2017.10.1 国庆清北 D1T1 zhx的字符串题

    题目背景 2017国庆清北D1T1 题目描述 你是能看到第一题的 friends 呢. ——hja 何大爷对字符串十分有研究,于是天天出字符串题虐杀 zhx.何大爷今天为 字符串定义了新的权值计算方法 ...

  2. 2017.10.3 国庆清北 D3T1 括号序列

    题目描述 LYK有一个括号序列,但这个序列不一定合法. 一个合法的括号序列如下: ()是合法的括号序列. 若A是合法的括号序列,则(A)是合法的括号序列. 若A和B分别是合法的括号序列,则AB是合法的 ...

  3. 2017.10.4 国庆清北 D4T2 正方形

    题目描述 在一个10000*10000的二维平面上,有n颗糖果. LYK喜欢吃糖果!并且它给自己立了规定,一定要吃其中的至少C颗糖果! 事与愿违,LYK只被允许圈出一个正方形,它只能吃在正方形里面的糖 ...

  4. 2017.10.6 国庆清北 D6T2 同余方程组

    题目描述 求关于x 的同余方程组 x%a1 = b1 x%a2 = b2 x%a3 = b3 x%a4 = b4 的大于等于0 的最小整数解. 输入输出格式 输入格式: 一行8 个整数,表示a1; b ...

  5. 2017.10.6 国庆清北 D6T1 排序

    题目描述 小Z 有一个数字序列a1; a2; .... ; an,长度为n,小Z 只有一个操作:选 定p(1<p<n),然后把ap 从序列中拿出,然后再插⼊到序列中任意位置. 比如a 序列 ...

  6. 2017.10.3 国庆清北 D3T3 解迷游戏

    题目描述 LYK进了一家古董店,它很想买其中的一幅画.但它带的钱不够买这幅画. 幸运的是,老板正在研究一个问题,他表示如果LYK能帮他解出这个问题的话,就把这幅画送给它. 老板有一个n*m的矩阵,他想 ...

  7. 2017.10.3 国庆清北 D3T2 公交车

    题目描述 LYK在玩一个游戏. 有k群小怪兽想乘坐公交车.第i群小怪兽想从xi出发乘坐公交车到yi.但公交车的容量只有M,而且这辆公交车只会从1号点行驶到n号点. LYK想让小怪兽们尽可能的到达自己想 ...

  8. 2017.10.4 国庆清北 D4T1 财富

    (其实这题是luogu P1901 发射站 原题,而且数据范围还比luogu小) 题目描述 LYK有n个小伙伴.每个小伙伴有一个身高hi. 这个游戏是这样的,LYK生活的环境是以身高为美的环境,因此在 ...

  9. 2017.10.7 国庆清北 D7T1 计数

    题目描述 给出m个数a[1],a[2],…,a[m] 求1~n中有多少数不是a[1],a[2],…,a[m]的倍数. 输入输出格式 输入格式: 输入文件名为count.in. 第一行,包含两个整数:n ...

随机推荐

  1. CSS两列布局

    方法1:左边设置绝对定位,右边设置左外边距,大小和左边的宽度相等 //CSS部分: .contain{ position :relative; height: 300px; } .left{ posi ...

  2. React学习:状态(State) 和 属性(Props)

    State 与 Props 区别props 是组件对外的接口,state 是组件对内的接口.组件内可以引用其他组件,组件之间的引用形成了一个树状结构(组件树),如果下层组件需要使用上层组件的数据或方法 ...

  3. C# 将Excel导出PDF

    1.安装所需包,使用nuget安装所需包 1.1.Spire.Xls 1.2.iTextSharp.text.pdf 2.Spire.Xls介绍 将Excel转换为PDF是一个很常用的功能,常见的转换 ...

  4. Ubuntu安装KScope

    命令安装 # apt-get install kscope 1. 编译安装 # tar xvf kscope-1.9.4.tar.gz # cd kscope-1.9.4 # qmake # make ...

  5. go语言 goquery爬虫

      goquery 类似ruby的gem nokogiri goquery的选择器功能很强大,很好用.地址:https://github.com/PuerkitoBio/goquery 这是一个糗百首 ...

  6. Delphi对于文件的读写操作

    delphi文件操作 取文件名 ExtractFileName(FileName); 取文件扩展名: ExtractFileExt(filename); 取文件名,不带扩展名: 方法一: Functi ...

  7. java线程的生命周期及五种基本状态

    一.线程的生命周期及五种基本状态 关于Java中线程的生命周期,首先看一下下面这张较为经典的图: 上图中基本上囊括了Java中多线程各重要知识点.掌握了上图中的各知识点,Java中的多线程也就基本上掌 ...

  8. p1.BTC-密码学的原理

    所谓加密货币是不加密的,区块链上所有的交易内容(包括:账户的地址,转账的地址)都是公开的. Bitcoin中主要用到密码学的中的两个功能:Hash和签名. 一 Hash Cryptographic h ...

  9. 加标签的continue用法

    1.加标签的continue,类似于C语言的goto语句

  10. LB_Yi

    LB_Yi 简述 LB_Yi也是一种比较常见的下界函数,在时间序列的筛选中十分常见.是由Yi在Kim的基础上设计的下界函数. 公式 LB_Yi的公式如下: 从公式中可以明显的看出,其实就是把大于序列最 ...