题目链接:传送门

Description

求一个字符串中所有不相交的回文串对

Solution

回文自动机裸题,正着加一遍反着加一遍即可 当然也可以用Manacher A掉

Code

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
    #include <bits/stdc++.h>
#define LL long long

using namespace std;

const int Maxn = 100000 + 100;

int S[Maxn];
char S1[Maxn];
LL Sum[Maxn];
int cnt;

struct tree
{
int cnt, ch[30], len, fail;
};

namespace PAM
{
tree Tree[Maxn];
int root0, root1, now, n;

inline void init ()
{
memset(Tree, 0, sizeof Tree);
memset(S, -1, sizeof S);
n = 0;
cnt = -1;
now = 0;
root0 = ++cnt, root1 = ++cnt;
S[0] = -1;
Tree[root0].fail = root1;
Tree[root0].len = 0;
Tree[root1].len = -1;
}

inline int get_fail (int now)
{
while (S[n - Tree[now].len - 1] != S[n]) now = Tree[now].fail;
return now;
}

inline int add (int c)
{
S[++n] = c;
now = get_fail(now);
if (!Tree[now].ch[c])
{
int x = ++cnt;
Tree[x].len = Tree[now].len + 2;
Tree[x].fail = Tree[get_fail(Tree[now].fail)].ch[c];
Tree[x].cnt = Tree[Tree[x].fail].cnt + 1;
Tree[now].ch[c] = x;
}
now = Tree[now].ch[c];
return Tree[now].cnt;
}
}

int main()
{
#ifdef hk_cnyali
freopen("A.in", "r", stdin);
freopen("A.out", "w", stdout);
#endif

while (~scanf("%s", S1))
{
PAM :: init();
int N = strlen(S1);
Sum[N] = 0;
for (int i = N - 1; i >= 0; --i)
Sum[i] = Sum[i + 1] + (LL)PAM :: add(S1[i] - 'a' + 1);
PAM :: init();
LL Ans = 0;
for (int i = 0; i < N; ++i)
Ans += (LL)((LL)PAM :: add(S1[i] - 'a' + 1) * Sum[i + 1]);
cout<<Ans<<endl;
}
return 0;
}


3.16 Upd
--------

今天无聊把A题manacher魔改一番A掉了这道题 原来用manacher做这道题更简单

#include <bits/stdc++.h>
#define int long long

using namespace std;

const int Maxn = 2e5 + 10 ;

char S[Maxn], A[Maxn];
int P[Maxn];
int Sum1[Maxn], Sum2[Maxn];
int L[Maxn], R[Maxn];

int N;

inline void Init ()
{
memset(P, 0, sizeof P);
memset(A, 0, sizeof A);
memset(L, 0, sizeof L);
memset(R, 0, sizeof R);
memset(Sum1, 0, sizeof Sum1);
memset(Sum2, 0, sizeof Sum2);
}

inline void Manacher ()
{
N = strlen(S + 1);
for (int i = 1; i <= N; ++i)
A[i * 2] = S[i], A[i * 2 - 1] = '#';
A[0] = '%', A[N * 2 + 1] = '#';
N = N * 2 + 1;
for (int i = 0; i <= N; ++i) S[i] = A[i];

int id = 0, Max = 0;
for (int i = 1; i <= N; ++i)
{
if (i < Max)
P[i] = min(P[2 * id - i], Max - i);
else P[i] = 1;
while (S[i + P[i]] == S[i - P[i]]) P[i] ++;
if (Max < i + P[i] - 1)
{
Max = i + P[i] - 1;
id = i;
}
}
}

inline void Solve ()
{
Manacher();
for (int i = 1; i <= N; ++i)
Sum1[i - P[i] + 1] += 1, Sum1[i + 1] -= 1;
for (int i = 1; i <= N; ++i)
{
Sum1[i] += Sum1[i - 1];
if (!(i % 2)) L[i / 2] = Sum1[i];
}

memset(Sum1, 0, sizeof Sum1);

for (int i = 1; i <= N; ++i)
Sum1[i] += 1, Sum1[i + P[i]] -= 1;
for (int i = 1; i <= N; ++i)
{
Sum1[i] += Sum1[i - 1];
if (!(i % 2)) R[i / 2] = Sum1[i];
}

memset(Sum2, 0, sizeof Sum2);

N /= 2;
for (int i = N; i >= 1; --i)
Sum2[i] = Sum2[i + 1] + L[i];
int Ans = 0ll;
for (int i = 1; i < N; ++i)
(Ans += Sum2[i + 1] * R[i]);
cout<<Ans<<endl;

}

main()
{
#ifdef hk_cnyali
freopen("A.in", "r", stdin);
freopen("A.out", "w", stdout);
#endif
while (~scanf("%s", S + 1))
{
Init();
Solve();
memset(S, 0, sizeof S);
}
return 0;
}