回文串问题分析

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 }
相关文章
相关标签/搜索