庞果网---回文字符串
来源:互联网 发布:连接网络将服务器 编辑:程序博客网 时间:2024/04/28 19:35
题目:
回文字符串是指从左到右和从右到左相同的字符串,现给定一个仅由小写字母组成的字符串,你可以把它的字母重新排列,以形成不同的回文字符串。
输入:非空仅由小写字母组成的字符串,长度不超过100;
输出:能组成的所有回文串的个数(因为结果可能非常大,输出对1000000007取余数的结果)。
例如:输入"aabb" 输出为2(因为“aabb”对应的所有回文字符串有2个:abba和baab)
函数头部
c:
int palindrome(const char *s);
c++
int palindrome(const string &s);
java
public static int palindrome(String s) ;
分析:
该题目意图是给定一组字符,让你调整顺序构成回文字符串,统计回文字符串的数量。
观察回文字符串构成,可以确定:
a. 每个字符数量为偶数,可以构造出回文字符串,此时回文字符串的长度为偶数。比如题目给出的例子;
b. 仅有一个数量为奇数的字符,可以构造出回文字符串,此时回文字符串的长度为奇数。比如aab,可以构造出aba;
c. 有多个数量为奇数的字符时,不能构成回文字符串,比如,ab就无法构成回文字符串。
长度为偶数的回文字符串(长度为奇数时也一样分析,只要将奇数的那个字母去掉,因为此字母只能在对称点上):
将长度为偶数的回文字符串从中间切开,则每一侧的字符串长度为原来的一半,而且每个字符的数量也为原来的一半。比如aabb可以构成回文字符串abba,切开之后,每一侧为ab,含有原来一半的字符。
假设调整左半侧字符数按需,右侧也相应改变,那么将半侧的字符串求出全排列,则既可以得出所有回文字符串的数量。为了好理解,我再举个例子:
原始串:aaaabbcc,可以看出每个字符为偶数个,用|表示分割线,则所有的回文字符串为:
aabc|cbaa abac|caba abca|acba
aacb|bcaa acab|baca acba|abca
baac|caab baca|acab
bcaa|aacb
cbaa|aabc caba|abac
caab|baac
一共有12种,为(4!/2!),即半侧字符串的全排列。
由上可知,问题转化为:
1. {Ai | 0<i<=n,n为字符种类数目};
2. Ai中奇数超过1个时返回0;
3. sum += Ai/2, M *= Ai!;
4. N = sum!;
5. N/M
在处理第3,4步时,采用分解质因数方法求中间结果,否则会出现溢出。
#include <map>#include <iostream>using namespace std;const int MOD = 1000000007;//通过分解质因数,统计每个质数的个数并保存在map中,根据分子还是分母情况在map中做加或减操作void primeAddStep(int n,map<int,int>& prime,int step){ while(n){ int tmp = n; for (int i=2;i<=tmp;i++){ while((tmp>=i) && (0 == tmp%i)){ prime[i] += step; tmp=tmp/i; } } --n; }}int palindrome(const string &s) { //保存每个字符数目 map<char,int> charCount; //分解质因数用 map<int,int> primeCount; map<char,int>::iterator iter_charCount; map<int,int>::iterator iter_primeCount; int sum = 0; int flag = 0; __int64 res = 1; //统计每个字符的个数 for(string::size_type i=0;i<s.size();++i){ iter_charCount=charCount.find(s[i]); if(iter_charCount != charCount.end()) ++iter_charCount->second; else charCount.insert(pair<char,int>(s[i],1)); } for(iter_charCount=charCount.begin();iter_charCount!=charCount.end();++iter_charCount){ //判断字符数目是否为奇数,若奇数超过1个直接返回0 if(iter_charCount->second&0x01){ if(0==flag) ++flag; else return 0; } //将字符数目减半 iter_charCount->second >> 1; //累加减半后的字符数目 sum += iter_charCount->second; //采用分解质因数方法,计算减半后的字符数目的阶乘的积 primeAddStep(iter_charCount->second,primeCount,-1); } //采用分解质因数方法,计算累计和的阶乘/字符数目阶乘积 primeAddStep(sum,primeCount,1); //根据约分之后的结果,计算出最终数量 for(iter_primeCount=primeCount.begin();iter_primeCount!=primeCount.end();++iter_primeCount){ for(int i=0;i<iter_primeCount->second;++i){ res = (res*iter_primeCount->first)%MOD; } } return int(res);}
最后感谢庞果网的各位网友的激情讨论
- 庞果网---回文字符串
- 回文字符串——庞果网
- 庞果网-回文字符串(failed)
- 庞果网挑战之回文字符串
- 还是回文 && 回文字符串
- 字符串回文
- 回文字符串
- 回文字符串
- 回文字符串
- 回文字符串
- 回文字符串
- 字符串回文
- 回文字符串
- 回文字符串
- 回文字符串
- 回文字符串
- 回文字符串
- 回文字符串
- 二叉树遍历,已知前序遍历与中序遍历,求后续遍历 使用java(递归方式)实现
- jquery 获得keycode
- Linux基本操作 4----- Linux系统目录架构
- 网络
- 白书的一些题目
- 庞果网---回文字符串
- Qt 编码惯例
- poj 1659
- java 最简易记事本,带详细注释,仅供参考!
- codeforces 187 (div2)题解
- cocos简单的3d渲染
- java中引用数据类型
- “第三方支付”盈利模式
- 表单隐藏域的应用