回文串问题分析
HDU CS505 实验室
与各位共享~
今天学长让我做一道编程题:
描述:一个字符串如“coco”,向其添加一个字符组成一个新的字符串,这个字符串可能会成为回文字符串。
输入:一个不超过10位长度的字符串
输出:向输入的字符串添加一个字符,判断产生的新字符串是否有可能是回文串,若是,则输出“YES”,否输出“NO”
分析:
首先想到的是穷举法,把添加一个字符后的所有新字符串都列出来,逐一判断是否是回文串。
添加的字符,理论上可以是任意字符,但是如果要尽可能使得生产的字符串是回文串,那么这个被添加的字符一般是输入字符串中含有的字符(本身是回文串,且位数是偶数的,可以在中间添加任意字符,此时新字符串都是回文串)。
所以,要提取出输入字符串中不同的字符,然后根据字符生成新的字符串。设输入字符串长度是Len,根据插入位置,每个字符可以得到Len+1个新字符串。如果从输入字符串中提取到的不同字符个数是n(n<=Len),那么生成的字符串总数是(Len+1)*n。又Len<=10,所以问题的最大规模为110个新字符串。
优化:
1、 输入字符串后,首先检测它是不是回文串,如果是回文串而且位数是偶数,那么直接输出“YES”,否则穷举判断
2、另外,穷举时,生成一个判断一个,一旦有一个是回文串,就停止生成,输出结果,程序结束。
代码(C++实现,代码只用了优化1):
用时:半小时~1小时,非专业ACM的人士
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种新字符串,判断这2个字符串是否是回文串,若是则输出“YES”,否则输出“NO”。
若一开始首尾字符相等,那么去掉首尾字符后的新字符串调用递归。
分析3(非递归思路):
回文串是以某个字符(奇数传)或某2个字符(偶数串)为中心,左右两边的字符相等的字符串。假如字符串有可能在加入一个字符后成为回文串,那么与加入的字符位置轴对称的另一个字符在源字符串中被删除掉得到的字符串也应该是回文串。
所以,只要把尝试抽离每一个位置的字符后得到的新字符串,判断其是否是回文串就可以知道。问题最大规模为运算10次检测。
总结:递归思路和非递归思路的计算规模相当,都是最大为10次检测。
代码(C++实现):
所以,可以根据判断输入字符串的首尾字符是否相等作为递归终止条件。若不相等,那么检测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 }