今天在leetcode上刷回文子串时发现了这个算法,是实现回文串寻找的时间复杂度为n的算法。
之前刷一些博客讲解真的不知所谓,越看越晕,但其实算法很简单,就是个从头到尾求len数组的过程
在这里推荐这篇博客,是在这篇博客看懂这个算法的(https://blog.csdn.net/dyx404514/article/details/42061017)
需要注意的细节是加#号和在标号0位置加$的原因。
接下来贴代码:
public static String longestPalindrome(String s) {
//char数组存放扩增后的string字符串
char p[]=new char [2*s.length()+3];
p[0]='$';p[1]='#';
p[2*s.length()+2]='\0';
//sum[i]即以i为中心的最大子串的半径
int sum[]=new int[2*s.length()+3];
sum[0]=1;sum[1]=1;
//填充数组
for(int i=1;i<=s.length();i++) {
p[2*i]=s.charAt(i-1);
p[2*i+1]='#';
}
//max存放当前最大回文半径,maxindex存放最大半径对应的中心
int max=-1;int maxindex=-1;
//求扩充后数组以i为中心的各个回文串长度,记录在sum[i]中
for(int i=2;i<2*s.length()+3;i++) {
int tem=-2;
//i大于当前最大位置
if(i>=max)
{sum[i]=getsum(p, i);tem=sum[i];}
else {
//小于时
if(sum[2*maxindex-i]+i-1<=max)
sum[i]=sum[2*maxindex-i];
else
{sum[i]=getsum(p, i);tem=sum[i];}
}
if(tem>max) {
max=tem;maxindex=i;
}
}
System.out.println(maxindex);
System.out.println(max);
int len=(max-1);
int j=0;
char returnarr[]=new char [len];
for(int i=maxindex-max+2;i<maxindex+max-1;i=i+2,j++)
returnarr[j]=p[i];
return String.valueOf(returnarr);
}
//求以i为中心的最长回文
public static int getsum(char p[],int i){
int sum=1;int a=i-1;int b=i+1;
while(a>=0&&b<p.length){
if(p[a]==p[b])
{sum++;a--;b++;}
else
break;
}
return sum;
}