zoukankan      html  css  js  c++  java
  • [APIO2014]回文串

    [APIO2014]回文串

    https://www.luogu.org/problemnew/show/P3649

    题目描述

    给你一个由小写拉丁字母组成的字符串 s。我们定义 s 的一个子串的存在值为这个子串在 s 中出现的次数乘以这个子串的长度。

    对于给你的这个字符串 s,求所有回文子串中的最大存在值。

    输入输出格式

    输入格式:

    一行,一个由小写拉丁字母(a~z)组成的非空字符串 s。

    输出格式:

    输出一个整数,表示所有回文子串中的最大存在值。

    输入输出样例

    输入样例#1: 
    abacaba
    
    输出样例#1: 
    7
    
    输入样例#2: 
    www
    输出样例#2: 
    4

    说明

    【样例解释1】

    用 |s|  表示字符串 s 的长度。

    一个字符串 s1s2ss 的子串是一个非空字符串 sisi+1sj,其中1ijs∣。每个字符串都是自己的子串。

    一个字符串被称作回文串当且仅当这个字符串从左往右读和从右往左读都是相同的。

    这个样例中,有 7 个回文子串 a,b,c,aba,aca,bacab,abacaba。他们的存在值分别为 4, 2, 1, 6, 3, 5, 7

    所以回文子串中最大的存在值为 77。

    第一个子任务共 8 分,满足 1s100。

    第二个子任务共 15 分,满足 1s1000。

    第三个子任务共 24 分,满足 1s10000。

    第四个子任务共 26 分,满足 1s100000。

    第五个子任务共 27 分,满足 1s300000。

    回文树裸题

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 #define lson l,mid,rt<<1
     4 #define rson mid+1,r,rt<<1|1
     5 #define sqr(x) ((x)*(x))
     6 #define pb push_back
     7 #define eb emplace_back
     8 #define maxn 1000005
     9 #define rep(k,i,j) for(int k=i;k<j;k++)
    10 typedef long long ll;
    11 typedef unsigned long long ull;
    12 
    13 const int MAXN = 300005 ;
    14 const int N = 26 ;
    15 
    16 struct Palindromic_Tree {
    17     int next[MAXN][N] ;///next指针,next指针和字典树类似,指向的串为当前串两端加上同一个字符构成
    18     int fail[MAXN] ;///fail指针,失配后跳转到fail指针指向的节点
    19     int cnt[MAXN] ;
    20     int num[MAXN] ;
    21     int len[MAXN] ;///len[i]表示节点i表示的回文串的长度
    22     int S[MAXN] ;///存放添加的字符
    23     int last ;///指向上一个字符所在的节点,方便下一次add
    24     int n ;///字符数组指针
    25     int p ;///节点指针
    26 
    27     int newnode ( int l ) {///新建节点
    28         for ( int i = 0 ; i < N ; ++ i ) next[p][i] = 0 ;
    29         cnt[p] = 0 ;
    30         num[p] = 0 ;
    31         len[p] = l ;
    32         return p ++ ;
    33     }
    34 
    35     void init () {///初始化
    36         p = 0 ;
    37         newnode (  0 ) ;
    38         newnode ( -1 ) ;
    39         last = 0 ;
    40         n = 0 ;
    41         S[n] = -1 ;///开头放一个字符集中没有的字符,减少特判
    42         fail[0] = 1 ;
    43     }
    44 
    45     int get_fail ( int x ) {///和KMP一样,失配后找一个尽量最长的
    46         while ( S[n - len[x] - 1] != S[n] ) x = fail[x] ;
    47         return x ;
    48     }
    49 
    50     void add ( int c ) {
    51         c -= 'a' ;
    52         S[++ n] = c ;
    53         int cur = get_fail ( last ) ;///通过上一个回文串找这个回文串的匹配位置
    54         if ( !next[cur][c] ) {///如果这个回文串没有出现过,说明出现了一个新的本质不同的回文串
    55             int now = newnode ( len[cur] + 2 ) ;///新建节点
    56             fail[now] = next[get_fail ( fail[cur] )][c] ;///和AC自动机一样建立fail指针,以便失配后跳转
    57             next[cur][c] = now ;
    58             num[now] = num[fail[now]] + 1 ;
    59         }
    60         last = next[cur][c] ;
    61         cnt[last] ++ ;
    62     }
    63 
    64     void count () {
    65         for ( int i = p - 1 ; i >= 0 ; -- i ) cnt[fail[i]] += cnt[i] ;
    66         ///父亲累加儿子的cnt,因为如果fail[v]=u,则u一定是v的子回文串!
    67     }
    68 };
    69 
    70 int main(){
    71     #ifndef ONLINE_JUDGE
    72       //  freopen("input.txt","r",stdin);
    73     #endif
    74     std::ios::sync_with_stdio(false);
    75     string str;
    76     Palindromic_Tree pt;
    77     pt.init();
    78     cin>>str;
    79     for(int i=0;i<str.length();i++) pt.add(str[i]);
    80     ll ans=0;
    81     pt.count();
    82     for(int i=2;i<=pt.p;i++){
    83         ans=max(ans,1LL*pt.cnt[i]*pt.len[i]);
    84     }
    85     cout<<ans<<endl;
    86 }
    View Code
  • 相关阅读:
    Oracle86和92语法的连接,子查询,集合的操作
    Oracle笛卡尔积,分组,多表连接
    Oracle排序,伪列,字符函数,数字函数,日期行数
    Oracle基本的数据类型以及简单sql查询
    用while语句打印阶乘
    Switch小练习
    if语句多表达式与一个表达式
    三元操作符
    整数的二进制表达
    与或
  • 原文地址:https://www.cnblogs.com/Fighting-sh/p/10423538.html
Copyright © 2011-2022 走看看