最常回文串和最长回文序列
来源:互联网 发布:优化交通组织工作 编辑:程序博客网 时间:2024/06/08 12:44
最长回文串
两种方法
一种是使用动态规划的,这里的动态规划和最长公共子序列类似,但是计算表格的时候只要计算一般,而且是按照对角线来推进的
void subPalindrome2(char *A,char *sub){int len=strlen(A);int i=0,j=0,sublen;int maxsublen=1;memset(hp,0,N*N*sizeof(char));//初始化sublen=1,2的情况for(i=0;i<len;i++)hp[i][i]='T';for(i=1;i<len;i++){if(A[i-1]==A[i]){maxsublen=2;hp[i-1][i]='T';}elsehp[i-1][i]='F';}//规划sublen>2for(sublen=3;sublen<=len;sublen++){for(i=0,j=sublen-1;j<len;i++,j++){if(A[i]==A[j]){hp[i][j]=hp[i+1][j-1];if(hp[i+1][j-1]=='T')maxsublen=sublen;}elsehp[i][j]='F';}}for(i=0;i<len;i++){for(j=0;j<len;j++)printf("%c ",hp[i][j]);printf("\n");}//找出最大字串for(i=0,j=maxsublen-1;j<len;i++,j++){if(hp[i][j]=='T')break;}for(int k=i;k<=j;k++)sub[k-i]=A[k];}
第二种方法是Manacher算法
void Manacher(char *st,char* sub){//创建临时的字符串int len=strlen(st);char* T=(char*)calloc(len*2+3,sizeof(char));T[0]='@';T[2*len+2]='$';//防止首尾越界int i,maxid=0;for(i=1;i<=len*2;i+=2){T[i]='#';T[i+1]=st[i/2];}T[2*len+1]='#';//建立回文半径数组(包括回文中心)int* R=(int*)calloc(len*2+2,sizeof(int));R[0]=0;int P=0,P0=0;for(i=1;i<=2*len+1;i++){if(i<P)R[i]=min(P-i,R[2*P0-i]-1);elseR[i]=1;while(T[i+R[i]]==T[i-R[i]])R[i]++;if(i+R[i]-1>P){P=i+R[i]-1;P0=i;}if(R[maxid]<R[i])maxid=i;}//提取回文子串int k;for(k=0,i=maxid-R[maxid]+1;i<maxid+R[maxid]-1;i++)if(T[i]!='#')sub[k++]=T[i];sub[k]='\0';free(R);free(T);}
Manacher python实现
#coding:UTF-8__author__ = 'LQ'def manacher(st): st='@'+st+'$' T='#'.join(st)#T是转换过的数组 (P,P0,id)=(0,0,0)#P0是最远回文半径对应的中心,P是对应的最远回文半径,id是最大回文半径对应的中心, #回文半径包含中心点,下标从1开始,下标i对应的回文串为[i-(R[i]-1),i+(R[i]-1)] R=[0]#用来保存回文半径 for i in range(1,len(T)-1): if i<P: r=min(P-i,R[2*P0-i]-1) else: r=1 while T[i+r]==T[i-r]:r+=1 R.append(r) (P0,P)=(i,r+i-1) if r+i-1>P else (P0,P) id=id if R[id]>r else i #输出回文串 sub=T[id-(R[id]-1):id+(R[id])] sub=sub.replace('#','') return subif __name__=="__main__": print manacher('BBABCCBCAB')
最长子序列的思想和上面字符串的思想类似,,也是动态规划
//最长回文子序列void LPS(char *st,char* sub){memset(hp,0,N*N*sizeof(char));int len=strlen(st);int i,j;for(i=0;i<len;i++){hp[i][i]=1;dir[i][i]='o';//表示起点}int sublen;//动态规划长度大于2的字串,这里注意,对于i>j的串我们已经把hp[i][j]=0,所以计算sublen=2可以统一到下面的循环for(sublen=2;sublen<=len;sublen++){for(i=0;i<len-sublen+1;i++){j=i+sublen-1;if(st[i]==st[j]){dir[i][j]='+';hp[i][j]=hp[i+1][j-1]+2;}else{if(hp[i][j-1]>hp[i+1][j]){hp[i][j]=hp[i][j-1];dir[i][j]='R';}else{hp[i][j]=hp[i+1][j];dir[i][j]='U';}}//这里注意起点可能也是"aa"这样的串!!!if(sublen==2)dir[i][j]='o';}}//for(i=0;i<len;i++)//{//for(j=0;j<len;j++)//printf("%c ",dir[i][j]);//printf("\n");//}//printf("%d\n",hp[0][len-1]); //回溯出最长回文串i=0,j=len-1;int pbeg=0,pend=hp[0][len-1]-1;while(dir[i][j]!='o'){if(dir[i][j]=='+'){sub[pbeg++]=sub[pend--]=st[i];i++,j--;}if(dir[i][j]=='U')i++;if(dir[i][j]=='R')j--;}sub[pbeg]=sub[pend]=st[i];//如果起点是一个字符pbeg=pend,如果是两个字符则不相等}
0 0
- 最常回文串和最长回文序列
- 最长回文子串和回文子序列
- 最长回文串子序列
- 最长回文子串 与 最长回文子序列
- 最长回文子串、回文子序列、公共子序列
- 最长回文子序列
- 最长回文子序列
- MANACHER 最长回文序列
- 最长回文子序列
- 最长回文子序列
- 最长回文子序列
- 最长回文子序列
- 最长回文子序列
- 最长回文子串、最长回文子序列、回文子序列个数
- 算法导论—最长回文子串和子序列
- 最长回文子串/最大回文子序列
- 最长公共子串、最长公共子序列、最长回文子串、最长回文子序列、回文子串个数
- 最长回文子串or子序列
- 【转载】OpenVPN下载、安装、配置及使用详解
- zzy
- 写好Java代码的30条经验总结
- java 读取二维码
- 蓝桥杯 算法提高 最大乘积
- 最常回文串和最长回文序列
- hdu 2018 母牛的故事
- JavaScript学习(五)
- Java中的substring真的会引起内存泄露么?
- JS错误的诊断与修复
- C语言和C++中的动态内存分配
- @property、@synthesize关键字和点语法
- Java 生成二维码
- LoopViewPager可以循环播放的ViewPager