回文字符串是指从左到右和从右到左相同的字符串,现给定一个仅由小写字母组成的字符串,你可以把它的字母重新排列,以形成不同的回文字符串。 输入:非空仅由小写字母组成的字符串,长度不超过100;
输出:能组成的所有回文串的个数(因为结果可能非常大,输出对1000000007取余数的结果)。
例如:输入"aabb" 输出为2(因为“aabb”对应的所有回文字符串有2个:abba和baab)
又是结果对1000000007取余的,看到这个我就感觉大数据会出现了,结果我果断没过,查了一下网友的给的测试案例:
s=“zsmjajrycysuqjvyyraqvoyggmjgsuiyvclurvmygoivmsurgxsyyblvbgxsszlsly”
结果是493584849
我的是:
下面说一下我的思想,希望各位指点一下:
这题目很明显是个集合的问题,为了组成回文字符串必定会对称,若是奇数个字符,则中间随意,即字符中会有一个是单独的,若是偶数个字符,则每个字符都必须是偶数的。
所以total = length / 2;
总数的阶乘 / 每个字母出现的个数的阶乘<除以2以后的>
若是直接用 50! / X1! /X2!...这是肯定会超限的,所以这时候引用一个%1000000007;
我是将total!一点一点来的,然后同时也不断的进行/num,不过可能是因为中间%1000000007,一不小心弄出尴尬的数,后面/num强制转换了<个人认为的,正在研究,各位帮忙一下>;
贴出我的代码吧,希望各位给点建议:
#include <cstdio>
#include <cstring>
#include <string>
#include <iostream>
using namespace std;
int palindrome(const string &s){
long long int result = 1;
int totalLen = 0;
int countOdd = 0; //奇数字母的个数,超过两个回文的即为0个
int count[26] = {0};
for (int i = 0; s[i] != '\0'; i++) //统计各个字母出现的个数
{
count[s[i]-'a']++;
}
for (int i = 0; i < 26; i++)
{
if (count[i] % 2 == 1)
{
countOdd++;
}
count[i] /= 2; //将字母的出现次数为一半,只需考虑一半的字符串,因为是回文!
}
if (countOdd > 1)
{
return 0; //超过两次以上的奇数个字母
}
for (int i = 0; i < 26; i++) //集合
{
if (count[i] == 1) //出现一次直接算集合即可
{
totalLen++;
result = result * totalLen;
result %= 1000000007;
}
else if (count[i] > 1) //出现两次及以上需要除去count[i]!<阶乘>
{
int num = 1;
while (count[i]--)
{
totalLen++; //记录长度
result = result * totalLen / num ; //结果 //将字母的发生次数相除即/count[i]!
result %= 1000000007;
num++; //每个字母发生次数
}
}
else ;
}
return result;
}
//start 提示:自动阅卷起始唯一标识,请勿删除或增加。
int main()
{
cout<<palindrome("hqaymehhrsfuqrpahrimsxftuxqrpsejouuehaqtsryxjhearxmogmi");
return 0;
}
//end //提示:自动阅卷结束唯一标识,请勿删除或增加。
我的偶然对了...
路过的大神给点建议吧,谢谢了啊o(∩_∩)o