博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
回文树(回文自动机) - BZOJ 3676 回文串
阅读量:6151 次
发布时间:2019-06-21

本文共 2280 字,大约阅读时间需要 7 分钟。

  BZOJ 3676 回文串

Problem's Link:


 

Mean: 

analyse:

由于构造完回文自动机后,len[i]表示第i个回文串的长度,cnt[i]表示第i个回文串出现的次数,只需两者相乘去最大就可。

注意:i是从2开始,因为有两个长度为0和长度为-1的节点。

Time complexity: O(N)

 

Source code: 

/*
* this code is made by crazyacking
* Verdict: Accepted
* Submission Date: 2015-08-19-13.56
* Time: 0MS
* Memory: 137KB
*/
#include <queue>
#include <cstdio>
#include <set>
#include <string>
#include <stack>
#include <cmath>
#include <climits>
#include <map>
#include <cstdlib>
#include <iostream>
#include <vector>
#include <algorithm>
#include <cstring>
#define  LL long long
#define  ULL unsigned long long
using
namespace
std;
const
int
MAXN
=
300005 ;
const
int N
=
26 ;
char s
[
MAXN
];
struct
Palindromic_Tree
{
     
int
next
[
MAXN
][N
] ;
//next指针,next指针和字典树类似,指向的串为当前串两端加上同一个字符构成
     
int
fail
[
MAXN
] ;
//fail指针,失配后跳转到fail指针指向的节点
     
int
cnt
[
MAXN
] ;
     
int
num
[
MAXN
] ;
     
int
len
[
MAXN
] ;
//len[i]表示节点i表示的回文串的长度
     
int S
[
MAXN
] ;
//存放添加的字符
     
int
last ;
//指向上一个字符所在的节点,方便下一次add
     
int n ;
//字符数组指针
     
int p ;
//节点指针
     
int
newnode(
int
l)    
//新建节点
     
{
           
for(
int
i
=
0 ;
i
< N ;
++
i)
next
[p
][
i
]
=
0 ;
           
cnt
[p
]
=
0 ;
           
num
[p
]
=
0 ;
           
len
[p
]
=
l ;
           
return p
++ ;
     
}
     
void
init()  
//初始化
     
{
           p
=
0 ;
           
newnode(
0) ;
           
newnode(
-
1) ;
           
last
=
0 ;
           n
=
0 ;
           S
[n
]
=
-
1 ;
//开头放一个字符集中没有的字符,减少特判
           
fail
[
0
]
=
1 ;
     
}
     
int
get_fail(
int
x)    
//和KMP一样,失配后找一个尽量最长的
     
{
           
while(S
[n
-
len
[
x
]
-
1
]
!= S
[n
])
x
=
fail
[
x
] ;
           
return
x ;
     
}
     
void
add(
int
c)
     
{
           
c
-=
'a' ;
           S
[
++ n
]
=
c ;
           
int
cur
=
get_fail(
last) ;  
//通过上一个回文串找这个回文串的匹配位置
//            cout<<cur<<endl;
           
if(
!
next
[
cur
][
c
])    
//如果这个回文串没有出现过,说明出现了一个新的本质不同的回文串
           
{
                 
int
now
=
newnode(
len
[
cur
]
+
2) ;  
//新建节点
//                  cout<<get_fail(fail[cur])<<endl;
                 
fail
[
now
]
=
next
[
get_fail(
fail
[
cur
])][
c
] ;  
//和AC自动机一样建立fail指针,以便失配后跳转
//                  cout<<fail[now]<<endl;
                 
next
[
cur
][
c
]
=
now ;
                 
num
[
now
]
=
num
[
fail
[
now
]]
+
1 ;
           
}
last
=
next
[
cur
][
c
] ;
//            cout<<last<<endl;
           
cnt
[
last
]
++ ;
     
}
     
void
count()
     
{
           
for(
int
i
= p
-
1 ;
i
>=
0 ;
--
i)
cnt
[
fail
[
i
]]
+=
cnt
[
i
] ;
           
//父亲累加儿子的cnt,因为如果fail[v]=u,则u一定是v的子回文串!
     
}
}
run;
int
main()
{
     
scanf(
"%s"
,
&s);
     
int n
=
strlen(s);
     
run
.
init();
     
for(
int
i
=
0;
i
<n;
i
++)
run
.
add(s
[
i
]);
     
run
.
count();
     
LL
ans
=
LLONG_MIN;
     
for(
int
i
=
2;
i
<
run
.p;
++
i)
     
{
           
ans
=
max(
ans
,(
LL)
run
.
cnt
[
i
]
*
run
.
len
[
i
]);
     
}
     
cout
<<
ans
<<
endl;
     
return
0;
}

 

转载地址:http://zegya.baihongyu.com/

你可能感兴趣的文章
js插件---图片懒加载echo.js结合 Amaze UI ScrollSpy 使用
查看>>
java中string和int的相互转换
查看>>
P1666 前缀单词
查看>>
HTML.2文本
查看>>
Ubuntu unity安装Indicator-Multiload
查看>>
解决Eclipse中新建jsp文件ISO8859-1 编码问题
查看>>
7.对象创建型模式-总结
查看>>
1、块:ion-item
查看>>
【论文阅读】Classification of breast cancer histology images using transfer learning
查看>>
移动端处理图片懒加载
查看>>
jQuery.on() 函数详解
查看>>
谈缓存和Redis
查看>>
【转】百度地图api,根据多点注标坐标范围计算地图缩放级别zoom自适应地图
查看>>
用户调研(补)
查看>>
ExtJS之开篇:我来了
查看>>
☆1018
查看>>
oracle 去掉空格
查看>>
6.13心得
查看>>
Runtime类
查看>>
eclipse decompiler
查看>>