Datahub
数据改变生活

回文串

发表时间:2022-10-27 20:28

回文串

描述

给定一个字符串,求出该字符串有多少子串是回文串。

子串:字符串中连续的一段。比如字符串 abcd 里,bc、abc、a、bcd 都是子串。

回文串:字符串倒序写出来和该字符串相同。比如aba,倒序写出来也是aba,故 aba 是回文串。而 abab 不是回文串,因为倒过来写是 baba。

输入

输入一个字符串。

输出子串是回文串的个数。

样例 1 输入

样例 1 输

样例 1 解释

abab,abab,abab abab,abab,abab

样例 2

请查看下发文件内的 sample2_input.txt 和 sample2_output.txt。

限制

对于 50%的数据,字符串长度不超过 500; 对于 70%的数据,字符串长度不超过 2000;

对于 100%的数据,字符串长度不超过 500000。字符串为 26 个小写字母组成。

时间:2 sec

空间:512 MB

提示

[[[https://segmentfault.com/a/1190000003914228]

[这篇文章是求最长的回文串的,那么如何求回文串的数目呢?可以发现manacher 算法将每个位置为中心能延展出的最长回文串求出来了,那么这个最长回文串的一半(上取整) 就是以该点作为中心的回文串数目。]

[注意答案要用long long。]

代码

#include <iostream> #include<algorithm>

#pragma warning(disable:4996) using namespace std;

// ================= 代码实现开始 =================

const int N = 500005;

/* 请在这里定义你需要的全局变量 */

//s:变化后的s数组

//len:每个位置能向左拓展的最大长度(回文半径) char s[N * 2];

int len[N * 2];

// 计算str中有多少个回文子串

// 返回值:子串的数目

long long getAnswer(string str) {

/* 请在这里设计你的算法 */

int n = str.size();

//将字符串变为#a#b#c#d#这样的形式,下方认为#是0

for (int i = n; i; --i)

s[i << 1] = str[i - 1], s[i << 1 | 1] = 0;

//边界(位置0和n+1)设为不同于#的东西(即1和2)

n = n << 1 | 1;

s[1] = 0, s[0] = 1, s[n + 1] = 2;

//manacher算法

int cur = 1;

long long ans = 0;

for (int i = 2; i <= n; ++i)

{

int &now = len[i], pos = (cur << 1) - i;

now = max(min(len[pos], cur + len[cur] - i), 0);

while (s[i - now - 1] == s[i + now + 1])

++now;

if (i + now > cur + len[cur])

cur = i;

ans += ((now + 1) >> 1);//相当于now/2取上界

}

return ans;

}

// ================= 代码实现结束 =================

char _s[N];

int main() {

scanf("%s", _s + 1);

printf("%lld\n", getAnswer(_s + 1));

return 0;

}


上一篇邓老师数
下一篇矩形
文章分类: 数据结构例题
分享到:
QQ:258506508                                     联系电话:020-000000    000-000000                                   联系邮箱:xxx@.co.m                                     联系地址:XXX省XXX市XXX县XXX路