• 双倍回文[Shoi2011][bzoj2342]


    双倍回文[Shoi2011][bzoj2342]

    2342: [Shoi2011]双倍回文

    Time Limit: 10 Sec  Memory Limit: 128 MB
    Submit: 2820  Solved: 1088
    [Submit][Status][Discuss]

    Description

     

    Input

    输入分为两行,第一行为一个整数,表示字符串的长度,第二行有个连续的小写的英文字符,表示字符串的内容。

     

    Output

    输出文件只有一行,即:输入数据中字符串的最长双倍回文子串的长度,如果双倍回文子串不存在,则输出0

    Sample Input

    16
    ggabaabaabaaball

    Sample Output

    12

    HINT

    N<=500000

    Source

    题意就是要求一个回文串,这个回文串的一半也是回文串,那么,可以看出这个串的长度必须是4的倍数。。。。。真心想不出,想了30分钟,并没有做出来,对回文自动机的理解还不是很充分,看了题解,大部分用了马拉车,思维题,但也有充分利用回文自动机的性质;观察回文自动机上的fail链,也就是后缀链,它满足fail链连向的节点是这个节点最长的回文后缀,那么,当整个串都添加进去时,fail链也就成了fail树,连接了所有本质不同的回文串,而且,这个是一个有向的,由小的串往两边添加字符成大的串,所以就可以从根节点0号节点开始dfs,记录一个桶,表示长度为i的节点在以前出现过,就只要判断这个串的长度%4==0,并且长度为len/2的节点在以前出现过,这样就很好的解决了这个问题;

    主要是利用了fail链与fail树的性质,求出双倍回文!!

     1 #include<algorithm>
     2 #include<iostream>
     3 #include<cstdlib>
     4 #include<cstdio>
     5 #include<cmath>
     6 #include<map>
     7 #include"set"
     8 #include"queue"
     9 #include"vector"
    10 #include"iomanip"
    11 #include"cstring"
    12 #define inf 1<<29
    13 #define ll long long
    14 #define re register
    15 #define il inline
    16 #define rep(i,a,b) for(register int i=a;i<=b;++i)
    17 #define file(a) freopen(a".in","r",stdin),freopen(a".out","w",stdout);
    18 using namespace std;
    19 const int N=26,MAXN=500010;
    20 struct Edge{
    21     int to,net;
    22 }e[MAXN];
    23 int ans;
    24 int head[MAXN],num_e;
    25 il void link(int x,int y) {
    26     e[++num_e].to=y,e[num_e].net=head[x],head[x]=num_e;
    27 }
    28 struct Palindromic_Tree{
    29     int nxt[MAXN][N],fail[MAXN],len[MAXN],lst,n,p;
    30     int S[MAXN];
    31     il int newnode(int l) {
    32         for(re int i=0;i<N;++i)
    33             nxt[p][i]=0;
    34         len[p]=l;
    35         return p++;
    36     }
    37     il void init() {
    38         p=0;
    39         newnode(0);
    40         newnode(-1);
    41         n=0;lst=0;S[0]=-1;
    42         fail[0]=1;
    43     }
    44     il int get_fail(int x){
    45         while(S[n-len[x]-1]!=S[n]) x=fail[x];
    46         return x;
    47     }
    48     il void add(int c) {
    49         c-='a';
    50         S[++n]=c;
    51         int cur=get_fail(lst);
    52         if(!nxt[cur][c]) {
    53             int now=newnode(len[cur]+2);
    54             fail[now]=nxt[get_fail(fail[cur])][c];
    55             nxt[cur][c]=now;
    56             link(fail[now],now);
    57         }
    58         lst=nxt[cur][c];
    59     }
    60     int T[MAXN];
    61     il void dfs(int x) {
    62         if(len[x]%4==0&&T[len[x]/2]) ans=max(ans,len[x]);
    63         T[len[x]]++;
    64         for(int i=head[x];i;i=e[i].net)
    65             dfs(e[i].to);
    66         T[len[x]]--;
    67     }
    68 }Pam;
    69 char ch[MAXN];
    70 inline int gi() {
    71     re int res=0,f=1;re char ch=getchar();
    72     while((ch<'0'||ch>'9')&&ch!='-') ch=getchar();
    73     if(ch=='-') f=-1,ch=getchar();
    74     while(ch>='0'&&ch<='9') res=res*10+ch-'0',ch=getchar();
    75     return res*f;
    76 }
    77 int main(){
    78     file("Y");
    79     int n=gi();
    80     scanf("%s",ch);int len=strlen(ch);
    81     Pam.init();
    82     for(re int i=0;i<len;++i) Pam.add(ch[i]);
    83     Pam.dfs(0);
    84     cout<<ans;
    85     return 0;
    86 }
  • 相关阅读:
    sql连接查询中的分类
    HTML之页面镶嵌体验
    JavaScript之搜索框
    (转)Android之常用功能方法大集合
    JAVA之执行cmd命令
    Html之网页分屏浏览
    Javascript之三种按钮点击事件
    用JavaScript做一个小小设计
    JavaBean之简单应用JSP页面
    计算器
  • 原文地址:https://www.cnblogs.com/ypz999/p/7157635.html
Copyright © 2020-2023  润新知