研究了一下便于记忆的两种回文字串方法,代码如下:
#include <iostream> #include <string> using namespace std; //最大回文字串,有如下方法: //http://blog.csdn.net/linulysses/article/details/5634104 //动态规划法 /* xPy肯定不是回文,xPx是回文当且仅当P是回文,如下算法使用LP[i][j]表示aiai+1...aj是否是回文 LP[i][j]=true i>=j时候表示单个字符串 LP[i][j]=true i<j当且仅当LP[i+1][j-1]=true且S[i]=S[j] 否则 LP[i][j]=false 首先对于 长度进行 1-len 的循环 然后对于每个回文的起点i 再根据不同的长度做调整 o(n^2) */ string max_huiwen_dynamic(string s){ string huiwen; int len=s.length(),i,j,k,h_start=0,h_end=0; if(len<=0) return huiwen; bool **_LP=(bool**)malloc(sizeof(bool*)*len); for (i=0;i<len;i++) { _LP[i]=(bool*)malloc(sizeof(bool)*len); _LP[i][i]=true; } for (i=1;i<=len;i++)//长度循环 { for (j=0;j<len-i;j++) { k=i+j-1; if(i==j||(s[k]==s[j]&&_LP[j+1][k-1])){ _LP[j][k]=true; if(h_end-h_start<i){ h_end=k+1; h_start=j; } } else _LP[j][k]=false; } } huiwen.assign(s.begin()+h_start,s.begin()+h_end); return huiwen; } //Manacher算法 //http://www.cnblogs.com/houkai/p/3371807.html //利用先前计算好的一个保存以每个字符为中心点坐标的回文的长度,假设当前计算的点在回文区间内,则只需要查看是否和另一侧的相同即可。 //具有记忆性 string padding(string str) { string tStr; int len=str.length(); tStr.push_back('$'); for(int i=0;i<len;i++){ tStr.push_back('#'); tStr.push_back(str[i]); } tStr.push_back('#'); return tStr; } string Manacher(string s) { string tStr=padding(s),returnStr; int mx=0,pi=1,len=tStr.length(); //辅助数组 int*p=new int[len]; memset(p,0,sizeof(int)*len); for (int i=0;i<len;i++) { if(mx>i) p[i]=min(mx-i,p[2*pi-i]); else p[i]=1; while(i-p[i]>0&&i+p[i]<len&&tStr[i-p[i]]==tStr[i+p[i]]) p[i]++; if(i+p[i]>mx){ mx=p[i]+i; pi=i; } } int maxLen=0,pos=0; for (int i=0;i<len;i++) { if(maxLen<p[i]){ maxLen=p[i]; pos=i; } } //现在字符串位置pos/2 ,移动长度(maxlen-1)/2 returnStr.assign(s.begin()+(pos-maxLen)/2,s.begin()+(pos-maxLen)/2+maxLen-1); return returnStr; }