回文字符串


題目描述:

回文字符串是指從左到右和從右到左相同的字符串,現給定一個僅由小寫字母組成的字符串,你可以把它的字母重新排列,以形成不同的回文字符串。

輸入:非空僅由小寫字母組成的字符串,長度不超過100;

輸出:能組成的所有回文串的個數(因為結果可能非常大,輸出對1000000007取余數的結果)。

例如:輸入"aabb" 輸出為2(因為“aabb”對應的所有回文字符串有2個:abba和baab)

 

思路:

問題需要我們給出可行解,那么就需要梳理出清晰准確的因果關系:

在這26個字母的序列中,

Case<1>如果有大於1個元素的個數是奇數,那么無論如何都構不成回文

Case<2>如果有且僅有1個元素的個數是奇數,把它放在正中央,還是可以構成回文數的

Case<3>如果所有元素的個數都是偶數,亦可構成回文數

本質上可以把Case<1>和Case<2>當成同一情況予以處理

 

細節1:

對於可行的字符串,如何計算種數?

e.g.      aaaabbcccddddee

因為回文串具有對稱性這一性質,所以只需要考慮一半的元素:aabcdde(多余的C放中央,不需考慮)

需要對其進行全排列,上例就是7!,顯然這7!包含重復的序列,如何歸為正解呢?應該除以每個元素個數一半的階乘,原因自己考慮

設有arr[26],存放的是每個元素出現的個數,M為字符串的元素總數

那么ans = (M/2)!/(arr[0]/2)!*(arr[1]/2)!*…(arr[25]/2)!

 

細節2:

如果取最大字符串,長度為100,我們就需計算50!

而以下數據類型的存儲范圍是:

     int:                 2147483647                   (10位)------------12! = 479001600

long long(__int64):9223372036854775807 (19位)------------21! = 5.1090942e+19

所以如果暴力計算50!會溢出的

應對方法:對於ans = (M/2)!/(arr[0]/2)!*(arr[1]/2)!*…(arr[25]/2)!

不必先乘完再除,邊乘邊除

 

Source Code:

#include<stdio.h>
#include<string.h>

int arr[26];
char s[102];

int palindrome(const char *s) {
    int i,j,tmp,sum,item,death,len,count = 0;
    long long mul;
    memset(arr,0,sizeof(arr));
    len = strlen(s);
for(i = 0; i < len; i++) arr[s[i]-97] += 1;
    for(i = 0; i < 26 ;i++){
        tmp = arr[i];
        if(tmp % 2 == 1) count++;
        if(tmp == 0 || tmp == 1) continue;
        sum = 1;
        for(j = 2; j <= tmp/2; j++) sum *= j;
        arr[i] = sum;
    }
if (count > 1) return 0;
    mul = 1,item = 0;
for(i = 1; i <= len/2; i++){
        while((arr[item] == 0 || arr[item] == 1) && item < 26) item++;
        mul *= i;        
        if( item < 26 && mul % arr[item] == 0){
            mul /= arr[item];
            item++;
        }
        if(item >= 26){
            death = i;
            break;        
        }
    }
    for(i = death+1; i<= len/2; i++){
        mul = (mul*i) % 1000000007;
    }
    return mul;
} 
    
int main(){
    while(scanf("%s",s) != EOF){
        printf("%d\n",palindrome(s));
    }
    return 0;    
}

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM