hdu 5421 Victor and String

hdu 5421 Victor and String

支持双端插入的回文树。

考虑维护第二个 last 表示当前整个串的最长回文前缀。

往前 append 的时候可以直接那第二个 last 来跳 fail , 因为回文前缀和回文后缀是对称的。只有 getfail 的时候需要改一下,变成判断当前字符和前缀之后的字符是否相同。

还要注意,如果当前的前面/后面 的 last 是整个串,那么需要把另一个 last 也设置成整个串。

注意如果当前插入得到的回文串pam里面已经有了也要加上它的贡献!

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
#include<iostream>
#include<algorithm>
#include<cstring>
#include<cstdio>
using namespace std;
#define MAXN 300006
int n;
struct pam {
int son[MAXN][26] , fail[MAXN] , dep[MAXN] , len[MAXN] , s[MAXN * 3];
int last[2] , n = 0 , st = 100006 , en = st , p = 0; long long re = 0;
int newnode(int l) {
for (int i = 0; i < 26; i++)
son[p][i] = 0;
len[p] = dep[p] = l;
return p++;
}
void init( ) {
memset( s , -1 , sizeof s );
p = re = 0;
newnode( 0 ) , newnode( -1 );
st = en = 100006;
last[0] = last[1] = n = 0;
fail[0] = 1;
}
int getfail1( int u ) {
while( s[en - len[u] - 1] != s[en] ) u = fail[u];
return u;
}
int getfail2( int u ) {
while( s[st + len[u] + 2] != s[st + 1] ) {
u = fail[u];
}
return u;
}
void add( int u , bool af ) {
u -= 'a';
int cur;
if( af ) {
s[++ en] = u;
cur = getfail1( last[af] );
}
else s[st --] = u , cur = getfail2( last[af] );
if( !son[cur][u] ) {
int now = newnode( len[cur] + 2 );
fail[now] = son[af ? getfail1(fail[cur]) : getfail2(fail[cur])][u];
son[cur][u] = now;
dep[now] = dep[fail[now]] + 1 , re += dep[now];
} else re += dep[son[cur][u]];
last[af] = son[cur][u];
if( len[last[af]] == en - st ) last[af^1] = last[af];
}
int dif( ) {
return p - 2;
}
long long und( ) {
return re;
}
} pam ;

int main() {
int op; char ch[3];
while( cin >> n ) {
pam.init();
while( n -- ) {
scanf("%d",&op);
if( op == 1 ) {
scanf("%s",ch) , pam.add( ch[0] , 0 );
} else if( op == 2 ) {
scanf("%s",ch) , pam.add( ch[0] , 1 );
} else if( op == 3 ) {
printf("%d\n",pam.dif( ));
} else printf("%lld\n" , pam.und());
}
}
}
文章作者: yijan
文章链接: https://yijan.co/old68/
版权声明: 本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 Yijan's Blog