[2018.07.17 T2] Palindromes

本文介绍了一种使用回文自动机构造方法解决寻找字符串中所有回文子串最大存在值的问题,通过增量构造实时统计回文串的出现次数,并最终通过拓扑递推得出答案。

暂无链接

Palindromes

【问题描述】

纸上得来终觉浅,绝知此事要躬行。

有一个小写字符串 s。我们定义 s 的一个子串的存在值为这个子串在 s 中出现的次数乘以这个子串的长度。

对于给你的这个字符串 s,求所有回文子串中的最大存在值。

【输入格式】

一行,一个由小写字母(a~z)组成的非空字符串 s。

【输出格式】

输出一个整数,表示所有回文子串中的最大存在值。

【输入样例】

abacaba

【输出样例】

7

【样例说明】

在第一个样例中,回文子串有 7 个:a,b,c,aba,aca,bacab,abacaba,其中:

a 出现 4 次,其存在值为 4:1:1=4
b 出现 2 次,其存在值为 2:1:1=2
c 出现 1 次,其存在值为 l:1:l=l
aba 出现 2 次,其存在值为 2:1:3=6
aca 出现 1 次,其存在值为 1=1:3=3
bacab 出现 1 次,其存在值为 1:1:5=5
abacaba 出现 1 次,其存在值为 1:1:7=7

故最大回文子串存在值为 7。

【数据范围】

10%10%的输入数据 :1|S|1001≤|S|≤100

20%20%的输入数据 :1|S|10001≤|S|≤1000

40%40%的输入数据 :1|S|100001≤|S|≤10000

70%70%的输入数据 :1|S|1000001≤|S|≤100000

100%100%的输入数据 :1|S|3000001≤|S|≤300000

题解

不愧为最水的一场考试。

很裸的一道回文自动机,增量构造时即可统计每个回文串的出现次数,最后拓扑递推即可得到答案。

代码
#include<bits/stdc++.h>
using namespace std;
const int M=3e5+5;
char ch[M];
int last,odd=1,even=2,tot=2,p,cot[M],son[M][26],len[M],fail[M];
void in(){scanf("%s",ch+1);}
bool go(int v,int x,int pos){return ch[pos-len[v]-1]==ch[pos];}
void add(int x,int pos)
{
    for(;!go(last,x,pos);last=fail[last]);
    if(son[last][x])last=son[last][x];
    else
    {
        p=last,son[p][x]=++tot,len[tot]=len[p]+2;
        if(p==odd)fail[tot]=even;
        else{for(p=fail[p];!go(p,x,pos);p=fail[p]);fail[tot]=son[p][x];}
        last=tot;
    }
    ++cot[last];
}
void ac()
{
    int l=strlen(ch+1);
    last=odd,fail[odd]=fail[even]=odd,len[odd]=-1;
    for(int i=1;i<=l;++i)add(ch[i]-'a',i);
    long long ans=0;
    for(int i=tot;i>=1;--i)cot[fail[i]]+=cot[i],ans=max(ans,1ll*cot[i]*len[i]);
    printf("%lld",ans);
}
int main(){in();ac();}
### 三位回文数的定义 三位回文数是指一个三位数,其正读和反读都相同。例如 101、222、343 等,这些数从左向右读和从右向左读的结果是一样的。 ### 三位回文数的判断方法 判断一个三位数是否为回文数,可以通过比较其百位和个位数字是否相同。因为三位数的形式为 $abc$($a$ 为百位数字,$b$ 为十位数字,$c$ 为个位数字,且 $1\leq a\leq9$,$0\leq b\leq9$,$0\leq c\leq9$),若 $a = c$,则该三位数就是回文数。以下是用 Python 实现的代码: ```python def is_three_digit_palindrome(num): if 100 <= num <= 999: hundreds = num // 100 units = num % 10 return hundreds == units return False # 测试示例 print(is_three_digit_palindrome(121)) print(is_three_digit_palindrome(123)) ``` 也可以使用 C 语言实现,代码如下: ```c #include <stdio.h> #include <stdbool.h> bool is_three_digit_palindrome(int num) { if (num >= 100 && num <= 999) { int hundreds = num / 100; int units = num % 10; return hundreds == units; } return false; } int main() { printf("%d\n", is_three_digit_palindrome(121)); printf("%d\n", is_three_digit_palindrome(123)); return 0; } ``` ### 三位回文数的生成方法 三位回文数的百位可以从 1 到 9 取值,十位可以从 0 到 9 取值,个位与百位相同。因此,可以通过两层循环来生成所有的三位回文数。以下是 Python 代码示例: ```python three_digit_palindromes = [] for hundreds in range(1, 10): for tens in range(0, 10): num = hundreds * 100 + tens * 10 + hundreds three_digit_palindromes.append(num) print(three_digit_palindromes) ``` C 语言实现代码如下: ```c #include <stdio.h> int main() { for (int hundreds = 1; hundreds < 10; hundreds++) { for (int tens = 0; tens < 10; tens++) { int num = hundreds * 100 + tens * 10 + hundreds; printf("%d ", num); } } return 0; } ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

ShadyPi

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值