manacher应用

https://vjudge.net/contest/237352#problem/F

题意:给出一个字符串,判断该字符串能否分成三个回文串。

解法:运用manacher算法,求出以每个i为中心的回文串长度p[i],从而预处理出所有的前缀回文串和后缀回文串。

分别枚举每个前缀回文串和后缀回文串,判断中间的字符串是否也为回文串,判断方法为:找到中间字符串的中心点k,比较2*p[k]-1以及中间字符串长度的大小,若2*p[k]-1较大,则中间字符串也是回文串;否则不是。

manacher原理参考博客:https://segmentfault.com/a/1190000008484167 (求字符串的最长回文串长度)

manacher模板:

 1 #include <iostream>  
 2 #include <cstring>
 3 #include <algorithm>  
 4 
 5 using namespace std;
 6 
 7 char s[1000];
 8 char s_new[2000];
 9 int p[2000];
10 
11 int Init()
12 {
13     int len = strlen(s);
14     s_new[0] = '$';
15     s_new[1] = '#';
16     int j = 2;
17 
18     for (int i = 0; i < len; i++)
19     {
20         s_new[j++] = s[i];
21         s_new[j++] = '#';
22     }
23 
24     s_new[j] = '\0';  // 别忘了哦
25     
26     return j;  // 返回 s_new 的长度
27 }
28 
29 int Manacher()
30 {
31     int len = Init();  // 取得新字符串长度并完成向 s_new 的转换
32     int max_len = -1;  // 最长回文长度
33 
34     int id;
35     int mx = 0;
36 
37     for (int i = 1; i < len; i++)
38     {
39         if (i < mx)
40             p[i] = min(p[2 * id - i], mx - i);  // 需搞清楚上面那张图含义, mx 和 2*id-i 的含义
41         else
42             p[i] = 1;
43 
44         while (s_new[i - p[i]] == s_new[i + p[i]])  // 不需边界判断,因为左有'$',右有'\0'
45             p[i]++;
46 
47         // 我们每走一步 i,都要和 mx 比较,我们希望 mx 尽可能的远,这样才能更有机会执行 if (i < mx)这句代码,从而提高效率
48         if (mx < i + p[i])
49         {
50             id = i;
51             mx = i + p[i];
52         }
53 
54         max_len = max(max_len, p[i] - 1);
55     }
56 
57     return max_len;
58 }
59 
60 int main()
61 {
62     while (printf("请输入字符串:\n"))
63     {
64         scanf("%s", s);
65         printf("最长回文长度为 %d\n\n", Manacher());
66     }
67     return 0;
68 }

本题代码:

 1 #include <bits/stdc++.h>
 2 #include <iostream>
 3 #include <algorithm>
 4 #include <cstdio>
 5 #include <cstring>
 6 #include <string>
 7 #include <cmath>
 8 #include <cstdlib>
 9 #include <queue>
10 #include <stack>
11 #include <map>
12 #include <vector>
13 #include <set>
14 #include <bitset>
15 #include <iomanip>
16 #define ms(a, b) memset(a, b, sizeof(a));
17 using namespace std;
18 typedef long long LL;
19 typedef pair<int, int> pii;
20 const int INF = 0x3f3f3f3f;
21 const int maxn = 4e4 + 10;
22 const int MAXN = 2e4 + 10;
23 const double eps = 1e-8;
24 const int mod = 1e9 + 7;
25 char s[maxn], ne[maxn];
26 int pre[maxn], suf[maxn], p[maxn];
27 
28 void manacher() {
29     ne[0] = '$';
30     ne[1] = '#';
31     int j = 2;
32     int len1 = strlen(s);
33     for(int i = 0; i < len1; i++) {
34         ne[j++] = s[i];
35         ne[j++] = '#';
36     }
37     ne[j] = '\0';
38     int len = j;
39     int mx = 0;
40     int id;
41     for(int i = 1; i < len; i++) {
42         if(i < mx) {
43             p[i] = min(p[2*id-i], mx-i);
44         }
45         else p[i] = 1;
46         while(ne[i-p[i]] == ne[i+p[i]]) p[i]++;
47         if(i + p[i] > mx) {
48             mx = i + p[i];
49             id = i;
50         }
51     }
52 }
53 
54 int main()
55 {
56 #ifdef local
57     freopen("case.in","r",stdin);
58 //    freopen("out.in","w",stdout);
59 #endif
60     int T;
61     scanf("%d", &T);
62     while(T--) {
63         scanf("%s", s);
64         manacher();
65 //        for(int i = 1; i < len; i++) {
66 //            printf("%c ", ne[i]);
67 //        }
68 //        cout << endl;
69 //        for(int i = 1; i < len; i++) {
70 //            printf("%d ", p[i]);
71 //        }
72 //        cout << endl;
73         int len = strlen(ne);
74         int l = 0, r = 0;
75         for(int i = 1; i < len; i++) {
76             if(p[i] == i && i != 1) pre[l++] = p[i];
77             if(p[i] + i == len && i != len-1) suf[r++] = p[i];
78         }
79         int i, j;
80         for(i = l-1; i >= 0; i--) {
81             for(j = 0; j < r; j++) {
82                 int t1 = 2 * pre[i];
83                 int t2 = len - 1 - (2 * suf[j] - 1);
84                 if(t1 > t2) continue;
85                 int tmp = (t1 + t2) >> 1;
86 //                if(p[tmp] == 1) continue;
87                 if(2 * p[tmp] - 1 >= t2 - t1 + 1) break;
88             }
89             if(j < r) break;
90         }
91         if(i >= 0) printf("Yes\n");
92         else printf("No\n");
93     }
94     return 0;
95 }

猜你喜欢

转载自www.cnblogs.com/Sissi-hss/p/9478656.html