用manacher算法,求最长回文字符串的长度
第一步:manacher算法,有一个巧妙的做法,就是讲奇偶串变成一个问题考虑。具体做法是,在原字符串的每个相邻两个字符中间插入一个分隔符,首尾也要插入字符,但首尾字符不能相同,以免在下面进行判断时,数组越界。(注意:插入的字符必须在原字符串中未出现过)
例:原串 acddcabsddsb(设为s串,长度为l)
转化后 ?#a#c#d#d#c#a#b#s#d#d#s#b(设为st串)
st[0]='?';s[1]='#'; for(int i=0;i<l;i++) { st[2*i+2]=s[i]; st[2*i+3]='#'; } s[2*i+2]='\0';//此时st长度为L=2l+2;
第二步:判断st字符串中,以st[i]为中心元素的最长的回文字符串长度,即从st[i]向左右衍生进行判断;将结果存在一个数组中,如数组p[]中。
/*在i之前的元素中,分别以它们作为中心,找到一个得到的回文字符串右端点最大的元素,标记为id; 最大的右端点 标记为mx */ int mx=0;id=0; for(i=1;i<L;i++) { if(mx>i) p[i]=p[id*2-i]<mx-i?p[id*2-i]:mx-i; else p[i]=1; while(st[i-p[i]]==st[i+p[i]])p[i]++; if(mx<p[i]+i) { mx=p[i]+i; id=i; } }
第三步:输出原字符串中最长的回文字符串,这里用到了一个该算法的一个性质,即p[i]-1就是该回文字串在元字符串s中的长度;
int sum=0; for(int i=1;i<L;i++) { sum=max(sum,p[i]); } printf("%d\n",sum-1);