1.动态匹配
3.如何进行递推p[i] 矩阵:
② rad[i]
如图2,rad[i-k]的范围为青色,因为黑色的部分是回文的,且青色的部分在黑色的部分里面,根据定义,很容易得出:rad[i
③ rad[i]
如图,通过和第一种情况对比之后会发现,因为青色的部分没有超出黑色的部分,所以即使橙色的部分全等,也无法像第一种情况一样引出矛盾,因此橙色的部分是有可能全等的。但是,根据已知的信息,我们不知道橙色的部分是多长,因此就需要再去尝试和判断了。
之上理解 告诉macnacher算法的 回文最大长度的边界 与 新增入的p[i] 的位置关系 ,根据July的编程之法的理解中
id 表示最大回文长度的位置 ,求p[i]位置的值 假设已经知道p[0,1...i-1]的值
mx 表示id+p[id] :最大回文长度的边界
① 根据对称性 求出 i关于id 位置的 对称点 j=id-(i-id)=2id-i; 总共分为 mx>i 和mx<=i
② 当mx>i: 同时候 mx-i>p[i] 说明以s[j]为中心回文子串的包含在S[id]为中心的回文子串中 ,i与j对称
以s[i]为中心回文子串的包含在S[id]为中心的回文子串中对应上述过程中2 过程 S[i] 在最大回文长度之内。
// 动态规划
for(int len=2;len<=length;len++)// len 表示回文字符串长度,i表示回文子串初始位置
for(int i=0;i<length-len+1;i++)
{
int j=i+len-1;//子串的结束位置
if(p[i+1][j-1] && str.charAt(i)==str.charAt(j))
{
p[i][j]=true;
maxlength=len;
start=i;
}
}
if(maxlength>=2)
return str.substring(start,maxlength);
return null;
}
// 中心扩展法,回文的话,那么 其中心位置 前缀和后缀一定是相等,枚举 所有的中心位置
public static String findLongestOalindrome1(String str)
{// 字符串是从 0 位置开始进行索引
if(str==null) return null;
int start=0;int max=0;
int i,j,c = 0;int n=str.length();
for( i=0;i<str.length();++i)
{
// 处理奇数 以 i为中心,向两边扩展
for(j=0;(i-j)>=0 &&(i+j)<n;++j)
{
if(str.charAt(i-j)!=str.charAt(i+j))
{ break;}
c=2*j+1;
}
if(c>max)
{
max=c;
start=i-j+1;
}
// 处理偶数abba 明显i=b,j=0 判断 i-j(本身) 与 i+j+1(i+1)
for(j=0;(i-j)>=0 &&(i+j+1)<n;++j)
{ if(str.charAt(i-j)!=str.charAt(i+j+1))
{break;}
c=2*j+2;
}
if(c>max)
{
max=c;
start=i-j+1;
}
}
System.out.println(start);
return str.substring(start, max);
}
public static String findLongestOalindrome2(String str)
{
if(str == null||str.length() == 0)
return str;
StringBuilder sb=new StringBuilder();
sb.append('#');
for(int i=0;i<str.length();i++)
{
sb.append(str.charAt(i));
sb.append('#');
}
str=sb.toString();
int n=str.length();
// Manancher id 表示P[i] 最大回文子串位置 mx =max(p[i])+id 最大回文子串的边界
int id=0,mx=0,i;
int p[]=new int[str.length()];
// 从左往右遍历 str ,对于 i位置现已经知晓 p[0,1...i-1]中的值
for( i=1;i<str.length();i++)
{
if(mx>i)
{
p[i]=Math.min(p[2*id-i],mx-i);
}
else
{
p[i]=1;
}
// p[i]>=mx-i
while( i+p[i]<n &&i-p[i]>=0&&str.charAt(i+p[i])==str.charAt(i-p[i]))
p[i]++;
if(p[i]+i>mx)
{
mx=p[i]+i;
id=i;
}
}
/*****进行输出 找到P[i]最大值所对应的位置就是 最大回文子串位置**/
int max=0;
for( i=1;i<p.length;i++)
{
if(p[i]>max)
{
max=p[i];
id=i;
}
}
int start=id-max+1;
int end=id+max-1;
StringBuilder sb2=new StringBuilder();
for( i=start;i<=end;i++)
{
if(str.charAt(i)!='#')
sb2.append(str.charAt(i));
}
return sb2.toString();
}