manacher算法_求最长回文子串长度

很好的总结,转自:

http://blog.csdn.net/dyx404514/article/details/42061017

总结为:两大情况,三小情况。

两大情况:I. i <= p  

1.要处理的位置i及i为中心的回文半径Len[i] < p-i已经完全包含在某个回文中了,这种情况不用计算,len[i] = len[j]。

2.要处理的位置i在某个回文中,但是以i为中心的回文半径len[i] >= p-i,需要往后匹配,重新更新p,及对应的po和Len[i];

II. i > p

要计算的位置已经超出某个回文了,之前的回文已经没用,要重新计算新的位置了。只能挨个匹配了。

 1 // manacher.cpp : 定义控制台应用程序的入口点。
 2 //
 3 
 4 #include "stdafx.h"
 5 #include <iostream>
 6 #include <string>
 7 #include <vector>
 8 #include <iterator>
 9 using namespace std;
10 
11 string ManaStr(string &orgStr,int length)
12 {//构造“马拉车”串
13     if(length == 0)
14         return NULL;
15 
16     string manacherString(2*length+1,'#');
17     for(int i = 0;i < length;i++)
18         manacherString[2*i+1] = orgStr[i];
19 
20     cout<<manacherString<<endl;
21     return manacherString;
22 }
23 
24 int manacher(string &manStr,int manacherLen)
25 {//“马拉车”计算过程,主要是每个位置对应的回文半径数组的生成,pArr[i]
26     if(manacherLen == 0)
27         return 0;
28 
29     int Len[25];//回文半径数组
30     for(int i = 0; i <25;i++)
31         Len[i] = 0;
32     for(int i = 0; i <25;i++)
33         cout<<Len[i];
34     int po = 0;//某个回文中心
35     int mostRight = -1;//某个回文串最右的位置,并不包含这个位置
36     int result = 0;
37 
38     //for(int i = 0;i != manacherLen;i++)
39     for(int i = 0;i != 25;i++)
40     {
41         Len[i] = mostRight > i ? min(mostRight-i,Len[2*po-i]):1;
42         /*
43           当前位置i包含在某个回文串中,那么Len[i]的值就是i到mostRight或者
44           关于po对称的j位置的Len值(j = 2*po-i)
45         */
46         while(i+Len[i] < manacherLen && i-Len[i] >=0)
47         {
48             if(manStr[i - Len[i]] == manStr[i + Len[i]])
49                 Len[i]++;//检查是否可扩
50             else
51                 break;
52         }
53         if(i+Len[i] > mostRight)
54         {//扩到mostRight之外了,旧的回文串就不起作用了,更新成新的回文串
55             //mostRight = Len[i] + 1;!!!!!!艹!!!会死人啊
56             mostRight = Len[i] + i;
57             po = i;
58         }
59         result = max(result,Len[i]);
60     }
61     return result - 1;
62 }
63 
64 int _tmain(int argc, _TCHAR* argv[])
65 {
66     string originalString = "abc1234321ab";//结果应该为7
67     int originalLen = originalString.length();
68     //int originalLen = 12;
69     cout<<originalString<<endl;
70     string manacherString = ManaStr(originalString,originalLen);
71     int manStrLen = 2*originalLen + 1;
72     cout<<"原串中包含的最长回文长度为:"<<manacher(manacherString,manStrLen)<<endl;
73     system("pause");
74     return 0;
75 }
manacher

 一个变形题

 1 // manacher_.cpp : 定义控制台应用程序的入口点。
 2 //题目:给定一个串,求 在串的后边添加最小字符使得整体都是回文
 3 //解法:利用manacher算法,当mostRight == length的时候停止,并记录下Len[i]
 4 //      找到包含最后一个字符的回文串,之前的逆序就是要求的结果
 5 //例子:abcd123321,在后边加dcba就是回文,返回dcba。
 6 
 7 
 8 
 9 #include "stdafx.h"
10 #include <iostream>
11 #include <string>
12 using namespace std;
13 
14 string manStr(string &orgStr,int orgLen)
15 {
16     if(orgLen == 0)
17         return NULL;
18 
19     string manaString(2*orgLen+1,'#');
20     //string的一种构造方法string(num,ele)
21     for(int i = 0; i < orgLen; i++)
22         manaString[2*i+1] = orgStr[i];
23 
24     cout<<manaString<<endl;
25     return manaString;
26 }
27 
28 void manacherCore(string& mancherStr,int manaLen)
29 {
30     if(manaLen == 0)
31         return;
32     
33     int mostEnd = 0;
34     int mostRight = -1;
35     int po = 0;
36     int Len[21];
37     for(int i = 0; i< 21; i++)
38         Len[i] = 0;//初始化Len
39 
40     for(int i = 0;i != manaLen; i++)
41     {
42         Len[i] = mostRight > i? min(mostRight - i,Len[2*po-i]):1;
43         //while(i+Len[i] < manaLen && i- manaLen > -1)麻痹又写错
44         while(i+Len[i] < manaLen && i- Len[i] > -1)
45         {
46             if(mancherStr[i + Len[i]] == mancherStr[i - Len[i]])
47                 Len[i]++;
48             else
49                 break;
50         }
51         if(i + Len[i] > mostRight)
52         {
53             mostRight =i + Len[i];
54             po = i;
55         }
56         if(mostRight == manaLen)
57         {
58             mostEnd = Len[i];
59             break;
60         }
61     }
62     //string result(10-(mostEnd-1),'0');//保存结果的string
63     string result(10-mostEnd+1,'0');//这里应该是原串长度10
64     int resLen = result.length();
65 
66     for (int i = 0; i < resLen; i++)
67         result[resLen-i-1] = mancherStr[2*i+1];
68     cout<<result<<endl;
69     
70 }
71 
72 int _tmain(int argc, _TCHAR* argv[])
73 {
74     string orginalStr = "abcd123321";
75     cout<<orginalStr<<endl;
76     int orgLen = orginalStr.length();
77     string mancherStr = manStr(orginalStr,orgLen);
78     int manaLen = mancherStr.length();
79     manacherCore(mancherStr,manaLen);
80     system("pause");
81     return 0;
82 }
manacher变形
原文地址:https://www.cnblogs.com/lp3318/p/5676558.html