迴文串問題分析

HDU CS505  實驗室

與各位共享~

今天學長讓我作一道編程題:
        描述:一個字符串如「coco」,向其添加一個字符組成一個新的字符串,這個字符串可能會成爲迴文字符串。
        輸入:一個不超過10位長度的字符串
        輸出:向輸入的字符串添加一個字符,判斷產生的新字符串是否有多是迴文串,如果,則輸出「YES」,否輸出「NO」

分析:
    首先想到的是窮舉法,把添加一個字符後的全部新字符串都列出來,逐一判斷是不是迴文串。
    
    添加的字符,理論上能夠是任意字符,可是若是要儘量使得生產的字符串是迴文串,那麼這個被添加的字符通常是輸入字符串中含有的字符(自己是迴文串,且位數是偶數的,能夠在中間添加任意字符,此時新字符串都是迴文串)。

    因此,要提取出輸入字符串中不一樣的字符,而後根據字符生成新的字符串。設輸入字符串長度是Len,根據插入位置,每一個字符能夠獲得Len+1個新字符串。若是從輸入字符串中提取到的不一樣字符個數是n(n<=Len),那麼生成的字符串總數是(Len+1)*n。又Len<=10,因此問題的最大規模爲110個新字符串。
    
優化:
       一、 輸入字符串後,首先檢測它是否是迴文串,若是是迴文串並且位數是偶數,那麼直接輸出「YES」,不然窮舉判斷
        二、另外,窮舉時,生成一個判斷一個,一旦有一個是迴文串,就中止生成,輸出結果,程序結束。

代碼(C++實現,代碼只用了優化1):
用時:半小時~1小時,非專業ACM的人士

ios

 1 #include <iostream>
 2 #include <string>
 3 #include <vector>
 4 using namespace std;
 5  
 6 bool isHuiWenString(string &str)
 7 {
 8     for(int i=0,j=str.length()-1;i<str.length()/2+1;i++,--j)
 9     {
10         if(str[i]!=str[j])
11             return false;
12     }
13     return true;
14 }
15  
16 bool existInVector(char ch,vector<char> &vec)
17 {
18     bool flag=false;
19     if(vec.empty())
20         return flag;
21     for(vector<char>::iterator it = vec.begin();it!=vec.end();++it)
22         if(ch == *it){
23             flag = true;
24             break;
25         } 
26     return flag;
27 }
28  
29 bool existHuiWenVector(vector<string>& vstr)
30 {
31     bool flag=false;
32     if(vstr.empty())
33         return flag;
34     for(vector<string>::iterator it=vstr.begin();it!=vstr.end();it++)
35     {
36         if(isHuiWenString(*it)){
37             flag = true;
38             break;
39         } 
40     }
41     return flag;
42 }
43  
44 int main()
45 {
46     string str;
47     cin>>str;
48     //若是是迴文串且偶數位數
49     if(0 == str.length()%2 && isHuiWenString(str)){
50         cout<<"YES"<<endl;
51         return 0;
52     }
53  
54     //提取不一樣字符數
55     vector<char> charVec;
56     for(int i=0;i<str.length();i++)
57         if(!existInVector(str[i],charVec))
58             charVec.push_back(str[i]);
59     vector<string> vStr;
60     //getAllKindsString(vStr,charVec,str);
61     vector<char> vChar=charVec;
62  
63     //生成待檢測的全部新字符串
64     for(vector<char>::iterator ic=vChar.begin();ic!=vChar.end();++ic)
65     {
66         string temp = *ic+str;
67         vStr.push_back(temp);
68         temp =str+*ic;
69         vStr.push_back(temp);
70         for(int i=1;i<str.length();++i){
71             string Head = str.substr(0,i);
72             string Last = str.substr(i,str.length()-i);
73             string newString = Head+*ic+Last;
74             vStr.push_back(newString);
75         }
76     }
77     //對每個生成的字符串進行判斷
78     if(existHuiWenVector(vStr))
79         cout<<"YES"<<endl;
80     else
81         cout<<"NO"<<endl;
82  
83     //for(vector<char>::iterator it = charVec.begin();it!=charVec.end();++it)
84     //    cout<<*it;
85     //for(vector<string>::iterator it=vStr.begin();it!=vStr.end();++it)
86     //    cout<<*it<<endl;
87     return 0;
88 }

 

/*************************************如下爲朋友們的思路****************************************/

分析2(遞歸思路):
    窮舉法是生產全部的新字符串,而後對每個字符串進行判斷,然而加入一開始的輸入字符串首尾字符就不相等,那麼不論在中間如何插入字符生成新的字符串,都是非迴文串,而這部分是窮舉法會多餘計算的。
    因此,能夠根據判斷輸入字符串的首尾字符是否相等做爲遞歸終止條件。若不相等,那麼檢測2種狀況,將首字母添加於字符串後面,以及將尾字母添加到字符串前面時生成的2種新字符串,判斷這2個字符串是不是迴文串,如果則輸出「YES」,不然輸出「NO」。
   若一開始首尾字符相等,那麼去掉首尾字符後的新字符串調用遞歸。

分析3(非遞歸思路):
     迴文串是以某個字符(奇數傳)或某2個字符(偶數串)爲中心,左右兩邊的字符相等的字符串。假如字符串有可能在加入一個字符後成爲迴文串,那麼與加入的字符位置軸對稱的另外一個字符在源字符串中被刪除掉獲得的字符串也應該是迴文串。
    因此,只要把嘗試抽離每個位置的字符後獲得的新字符串,判斷其是不是迴文串就能夠知道。問題最大規模爲運算10次檢測。


總結:遞歸思路和非遞歸思路的計算規模至關,都是最大爲10次檢測。


代碼(C++實現):
 
 1 #include <iostream>
 2  
 3 using namespace std;
 4  
 5 bool isHuiWenString(const string &str)
 6 {
 7     for(int i=0,j=str.length()-1;i<str.length()/2+1;i++,--j)
 8     {
 9         if(str[i]!=str[j])
10             return false;
11     }
12     return true;
13 }
14  
15 //遞歸方法
16 bool judgeString(const string& str)
17 {
18     if(str[0] != str[str.length()-1]){
19         string s1 = str[str.length()-1]+str;
20         string s2 = str+str[0];
21         if(isHuiWenString(s1) || isHuiWenString(s2))
22             return true;
23         return false;
24     }
25     else return judgeString(str.substr(1,str.length()-2));
26 }
27  
28 //非遞歸方法
29 bool judgeString2(const string& str)
30 {
31     for(int i=0;i<str.length();i++)
32     {
33         string Head = str.substr(0,i);
34         string Last = str.substr(i+1,str.length()-i-1);
35         string newString = Head+Last;
36         if(isHuiWenString(newString))
37             return true;
38     }
39     return false;
40 }
41  
42 int main()
43 {
44     string str;
45     cin>>str;
46     string resultStr;
47    if(str.empty())
48         resultStr="NO";
49     //當str的長度小於等於2,或者str自己是迴文串,那麼必定能夠成爲迴文串
50     if(str.length() <= 2 || isHuiWenString(str))
51         resultStr = "YES";
52     //判斷字符串,其中judgeString是遞歸方法,judgeString2是非遞歸方法
53     if(judgeString(str))
54         resultStr = "YES";
55     else resultStr="NO";
56     cout<<resultStr<<endl;
57     return 0;
58 }
相關文章
相關標籤/搜索