经典算法——最长回文子串

来源:互联网 发布:js脚本小游戏 编辑:程序博客网 时间:2024/05/17 01:33
  1. #include<iostream>  
  2. #include<cstdio>    
  3. #include<string> //cin>>输入字符串必须添加的头文件  
  4. #include<cstring>//C++中使用memset必须添加的头文件  
  5. #include<algorithm>    
  6. #include<vector>  
  7. using namespace std;  
  8.   
  9. const int N = 2 * (1e6) + 3;  
  10. char s[N];  
  11. int p[N];  
  12.   
  13. //利用manacher算法求最长回文子串  
  14. void manacher(char* s, int len)  
  15. {  
  16.     p[0] = 1;  
  17.     int mx = 0, id = 0;  
  18.     for (int i = 1; i < len; i++)   
  19.     {  
  20.         p[i] = mx > i ? min(p[id * 2 - i], mx - i) : 1;  
  21.         while (s[i + p[i]] == s[i - p[i]])  p[i]++;  
  22.         if (i + p[i] > id + p[id])   
  23.         {  
  24.             id = i;  
  25.             mx = i + p[i];  
  26.         }  
  27.     }  
  28. }  
  29.   
  30. int main()  
  31. {  
  32.     int n;  
  33.     vector<string>vec;  
  34.     while (cin >> n)  
  35.     {  
  36.         vec.clear();  
  37.         for (int k = 0; k < n; ++k){  
  38.             cin >> s;  
  39.             vec.push_back(s);  
  40.         }  
  41.         for (int k = 0; k < n; ++k){  
  42.             memset(s, 0, sizeof(s));//每次求得一个字符串的最长回文子串后,必须将数组s和p清零,不然会对后面的结果产生影响  
  43.             memset(p, 0, sizeof(p));  
  44.             int len = vec[k].size();  
  45.             for (int j = 0; j < len; ++j){  
  46.                 s[j] = vec[k][j];  
  47.             }  
  48.             for (int i = len; i >= 0; i--)   
  49.             {  
  50.                 s[(i << 1) + 1] = '#';  
  51.                 s[(i << 1) + 2] = s[i];  
  52.             }  
  53.             s[0] = '*'//防止数组越界    
  54.             len = len * 2 + 2;  
  55.             manacher(s, len);  
  56.             int ans = 0;  
  57.             for (int i = 0; i < len; i++)  
  58.                 ans = max(ans, p[i] - 1);  
  59.             printf("%d\n", ans);  
  60.         }  
  61.         return 0;  
  62.     }  

0 0
原创粉丝点击