最长回文子串模板Manacher算法时间复杂度On.docx
- 文档编号:28878272
- 上传时间:2023-07-20
- 格式:DOCX
- 页数:9
- 大小:16.42KB
最长回文子串模板Manacher算法时间复杂度On.docx
《最长回文子串模板Manacher算法时间复杂度On.docx》由会员分享,可在线阅读,更多相关《最长回文子串模板Manacher算法时间复杂度On.docx(9页珍藏版)》请在冰豆网上搜索。
最长回文子串模板Manacher算法时间复杂度On
//最长回文子串模板
//hdu3068,最长回文子串模板,Manacher算法,时间复杂度O(n),相当快
#include
#include
#include
usingnamespacestd;
#defineM20000050
charstr1[M],str[2*M];//startfromindex1
intrad[M],nn,n;
voidManacher(int*rad,char*str,intn)/*str是这样一个字符串(下标从1开始):
举例:
若原字符串为"abcd",则str为"$#a#b#c#d#",最后还有一个终止符。
n为str的长度,若原字符串长度为nn,则n=2*nn+2。
rad[i]表示回文的半径,即最大的j满足str[i-j+1...i]=str[i+1...i+j],
而rad[i]-1即为以str[i]为中心的回文子串在原串中的长度*/
{
inti;
intmx=0;
intid;
for(i=1;i { if(mx>i) rad[i]=rad[2*id-i] rad[2*id-i]: mx-i; else rad[i]=1; for(;str[i+rad[i]]==str[i-rad[i]];rad[i]++) ; if(rad[i]+i>mx) { mx=rad[i]+i; id=i; } } } intmain() { inti,ans,Case=1; while(scanf("%s",str1)! =EOF) { nn=strlen(str1); n=2*nn+2; str[0]='$'; for(i=0;i<=nn;i++) { str[2*i+1]='#'; str[2*i+2]=str1[i]; } Manacher(rad,str,n); ans=1; for(i=0;i ans=rad[i]>ans? rad[i]: ans; printf("%d\n",ans-1); } return0; } //扩展kmp版,时间复杂度O(nlogn),稍慢 //hdu3068 /*给一个w长的字符串,求最长回文子串的长度 解题思路: 不是传说中的高深的后缀数组,而是扩展的kmp算法。 扩展kmp中,模式串与主串都有一个next向量,相应的next[i],记录该串的后缀与模式串的最大匹配数,关于扩展kmp的具体实现这里就不说了,现在只说一下解此题的思路: 令所给字符串为a,则找到中点mid位置,一后半段做为模式串,把a倒过来生成b,求出b串在该模式串的每一位的next1[i];在以字符串a的前半段的逆串作为模式串,求出a串在该模式串下的next2。 然后遍历a串的每一位,根据next1和next2就可以判断此处是否回文,但这个回文只能判断跨越中点mid的回文,因此这里要进行划分递归,分别在a的前半段和后半段重复此算法即可找到最大回文串。 */ #include #include #include usingnamespacestd; #defineN110005 chartmp1[N],tmp2[N],s[N],tt[N]; inttmp[N],ans,ne1[N],ne2[N]; char*rev(char*str,intll) { for(inti=0;i tt[i]=str[ll-i-1]; tt[ll]=0; returntt; } voidgetA(char*pat,int*aa) { intj=0; while(pat[1+j]&&pat[j]==pat[1+j]) j++; aa[1]=j; intk=1; intlen,l; for(inti=2;pat[i];i++) { len=k+aa[k]; l=aa[i-k]; if(l aa[i]=l; else { j=(0>len-i)? 0: len-i; while(pat[i+j]&&pat[j]==pat[i+j]) j++; aa[i]=j; k=i; } } } voidgetB(char*pat,char*str,int*bb,intlength) { getA(pat,tmp); intj=0; while(pat[j]&&str[j]&&pat[j]==str[j]) j++; bb[0]=j; intk=0; intlen,l; for(inti=1;i { len=k+bb[k]; l=tmp[i-k]; if(l bb[i]=l; else { j=(0>len-i)? 0: len-i; while(i+j j++; bb[i]=j; k=i; } } } voidfind(intl,intr) { if(r-l+1<=ans) return; intx; intmid=(l+r)/2; strncpy(tmp1,s+l,mid-l+1); tmp1[mid-l+1]=0; strncpy(tmp2,s+mid+1,r-mid); tmp2[r-mid]=0; getB(tmp2,rev(s+l,r-l+1),ne1,r-l+1); getB(rev(tmp1,mid-l+1),s+l,ne2,r-l+1); ne1[r-l+1]=ne2[r-l+1]=0; for(inti=l;i<=mid;i++) { if(ne2[i-l]*2>=mid-i+1) { x=mid-i+1+ne1[r-i+1]*2; if(ans ans=x; } } if(ans<2*ne2[mid+1-l]) ans=2*ne2[mid+1-l]; for(inti=mid+1;i<=r;i++) { if(ne1[r-i]*2>=i-mid) { x=i-mid+ne2[i-l+1]*2; if(ans ans=x; } } find(l,mid); find(mid+1,r); } intmain() { while(scanf("%s",s)! =EOF) { ans=1; find(0,strlen(s)-1); printf("%d\n",ans); } return0; } //下面注释掉的也对,只要把上面的rev函数换成下面的rev函数,并把find函数换成下面的solve函数就可以了 /* intnextb[N],nexta1[N],nexta2[N]; chara[N],b[N]; voidrev(char*a,intlen) { chart; for(inti=0;i t=a[i],a[i]=a[len-1-i],a[len-1-i]=t; } voidsolve(char*a,intlen) { if(len<=ans||len<2)return; intmid=len>>1; inti,j,k; for(i=mid;i b[i-mid]=0; rev(a,len); getB(b,a,nexta1,len); rev(a,len); for(i=0;i b[i]=0; getB(b,a,nexta2,len); nexta1[len]=nexta2[len]=0; for(i=0;i { if(nexta2[i]>=(mid-i)/2) { intx=mid-i+2*nexta1[len-i]; if(x>ans)ans=x; } } for(i=mid;i { if(nexta1[len-i]>=(i-mid)/2) { intx=i-mid+2*nexta2[i]; if(x>ans)ans=x; } } solve(a,mid-1); solve(a+mid,len-mid); } intmain() { inti,j,k; while(scanf("%s",a)! =EOF) { ans=1; solve(a,strlen(a)); printf("%d\n",ans); } } */
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 最长 回文 模板 Manacher 算法 时间 复杂度 On