Description
艾利斯顿商学院篮球队要参加一年一度的市篮球比赛了。拉拉队是篮球比赛的一个看点,好的拉拉队往往能帮助球队增加士气,赢得最终的比赛。所以作为拉拉队队长的楚雨荨同学知道,帮助篮球队训练好拉拉队有多么的重要。拉拉队的选拔工作已经结束,在雨荨和校长的挑选下,n位集优秀的身材、舞技于一体的美女从众多报名的女生中脱颖而出。这些女生将随着篮球队的小伙子们一起,和对手抗衡,为艾利斯顿篮球队加油助威。一个阳光明媚的早晨,雨荨带领拉拉队的队员们开始了排练。n个女生从左到右排成一行,每个人手中都举了一个写有26个小写字母中的某一个的牌子,在比赛的时候挥舞,为小伙子们呐喊、加油。雨荨发现,如果连续的一段女生,有奇数个,并且他们手中的牌子所写的字母,从左到右和从右到左读起来一样,那么这一段女生就被称作和谐小群体。现在雨荨想找出所有和谐小群体,并且按照女生的个数降序排序之后,前K个和谐小群体的女生个数的乘积是多少。由于答案可能很大,雨荨只要你告诉她,答案除以19930726的余数是多少就行了。
Input
输入为标准输入。第一行为两个正整数n和K,代表的东西在题目描述中已经叙述。接下来一行为n个字符,代表从左到右女生拿的牌子上写的字母。
Output
输出为标准输出。输出一个整数,代表题目描述中所写的乘积除以19930726的余数,如果总的和谐小群体个数小于K,输出一个整数-1。
Sample Input
5 3
ababa
Sample Output
45
样例说明
和谐小群体女生所拿牌子上写的字母从左到右按照女生个数降序排序后为ababa, aba, aba, bab, a, a, a, b, b,前三个长度的乘积为。
HINT
总共20个测试点,数据范围满足:
题意分析
对于一个长度为n的给定字符串,找出其中所有的回文字符串,按照回文串的长度降序排列,计算出前K个长度值的乘积(对19930726的余数),如果回文串的个数小于K个,则输出-1.
题中给的例子:对于一个长度为n=5的字符串“ababa”,计算出前k=3个回文串长度的乘积。
“ababa”的回文串从左到右共有9个(单独一个字符也算回文):“a”、“b”、“a”、“aba”、“b”、“bab”、“a”、“ababa”、“aba”,如果按降序排列的话是:“ababa”、“aba”、“bab”、“aba”、“a”、“b”、“a”、“b”、“a”,其长度分别是5、3、3、3、1、1、1、1、1,前三个的长度是5、3、3,所以乘积是5×3×3=45
解题思路
首先,这个题需要找出给定字符串的所有回文子串的长度,这个显然可以用马拉车算法,马拉车算法计算的数组(在本文中成为数组f[],在讲解manachar算法的那个帖子中称为数组p[])f[]的值就是每个字符为中心的回文串的半径长度,所以根据数组f[]计算出每种回文串的长度及其回文串的个数,最后按降序把长度最大的K个回文串长度值连乘得到结果即可,连乘可以使用快速幂的方法。
这个过程大体可以分为四步:
第一步:对原串使用manachar算法,计算出数组f[],记录下以每一个字符为中心的回文串半径长度,如“ababa”的f[]={0,1,2,1,0}。
第二步:通过对数组f[]的处理,得出每种回文串的长度 以及该种回文串的个数,比如“ababa”中,长度为5的回文串有1个(“ababa”),长度为3的回文串有3个(“aba”、“bab”、“aba”),长度为1的回文串有5个(“a”、“b”、“a”、“b”、“a”),总共有9个回文串。
第三步:看看回文串总数是不是大于K,如果小于,则输出“-1”,否则,从大到小连乘前k个回文串的长度,按照快速幂的方法连乘,例如“ababa”共有9个回文串,长度为5的有1个,长度为3的有3个,长度为1的有5个,则 ans=5×3×3 ,即 51×32=45
在这个过程中,还有一些细节问题需要注意,下面就分别详细介绍三个步骤
第一步
第一步是对原串用manachar算法求出它的f[]数组。manachar算法详细的介绍写过专门的帖子介绍,这里不赘述。但在这里有一些与标准manachar算法不一样的地方需要注意:manachar算法一般要在原串中插入“#”使得原串的长度都变成奇数再进行处理,插入“#”后的串也叫“双倍串”,长度是原来的2倍+1。而这个题中明确说要统计的和谐小群体的人数是奇数个。所以在这个题中,就不用往原串中插入“#”了,原来的串也可以叫做“单倍串”。
为什么呢,比如“ababa”,他的f[]={0、1、2、1、0},每一个f[i]的值是以第i个字符为中心的回文串的半径,如f[3]=2就是第3个字符“a”为中心的回文“ababa”的半径是2,因为是以某一个字符为中心,所以回文串的长度肯定是奇数的。
再比如“babbab”,左边的“bab”和右边的“bab”是对称相等的,所以“babbab”是一个长度为6的回文串,但由于数组f[]是以某一个字符为中心的回文串半径,所以他的f[]={0、1、0、0、1、0},因为是偶数长度的回文串,所以无论是以第3个字符“b”还是第4个字符“b”为中心,都没有回文串(回文串半径为0),因此偶数长度的回文串就不会统计在内了。
这一段的代码如下:
for (i=1;i<=n;i++) //n为字符串长度
{
if (i<=mx) f[i]=min(mx-i,f[2*id-i]);
else f[i]=0;
while (s[i+f[i]+1]==s[