zoukankan      html  css  js  c++  java
  • BZOJ 3676: [Apio2014]回文串

    3676: [Apio2014]回文串

    Time Limit: 20 Sec  Memory Limit: 128 MB
    Submit: 904  Solved: 356

    Description

    考虑一个只包含小写拉丁字母的字符串s。我们定义s的一个子串t的“出现值”为t在s中的出现次数乘以t的长度。请你求出s的所有回文子串中的最大出现值。 

    Input

    输入只有一行,为一个只包含小写字母(a -z)的非空字符串s。 

    Output


    输出一个整数,为逝查回文子串的最大出现值。 

    Sample Input

    【样例输入1】

    abacaba

    【样例输入2】

    www

    Sample Output

    【样例输出1】

    7

    【样例输出2】

    4

    HINT

    一个串是回文的,当且仅当它从左到右读和从右到左读完全一样。 

    在第一个样例中,回文子串有7个:a,b,c,aba,aca,bacab,abacaba,其中: 

    ● a出现4次,其出现值为4:1:1=4 

    ● b出现2次,其出现值为2:1:1=2 

    ● c出现1次,其出现值为l:1:l=l 

    ● aba出现2次,其出现值为2:1:3=6 

    ● aca出现1次,其出现值为1=1:3=3 

    ●bacab出现1次,其出现值为1:1:5=5 

    ● abacaba出现1次,其出现值为1:1:7=7 

    故最大回文子串出现值为7。 

    【数据规模与评分】 

    数据满足1≤字符串长度≤300000。

    解题:回文树

     1 #include <bits/stdc++.h>
     2 using namespace std;
     3 typedef long long LL;
     4 const int maxn = 300010;
     5 const int N = 26;
     6 struct PalindromicTree {
     7     int next[maxn][N],fail[maxn],cnt[maxn];
     8     int s[maxn],len[maxn],last,tot,n;
     9     int newnode(int length) {
    10         cnt[tot] = 0;
    11         memset(next[tot],0,sizeof next[tot]);
    12         len[tot] = length;
    13         return tot++;
    14     }
    15     int get_fail(int x) {
    16         while(s[n - len[x] - 1] != s[n]) x = fail[x];
    17         return x;
    18     }
    19     void init() {
    20         last = tot = n = 0;
    21         newnode(0);
    22         newnode(-1);
    23         s[n] = -1;
    24         fail[0] = 1;
    25     }
    26     void add(int c) {
    27         c -= 'a';
    28         s[++n] = c;
    29         int cur = get_fail(last);
    30         if(!next[cur][c]) {
    31             int now = newnode(len[cur] + 2);
    32             fail[now] = next[get_fail(fail[cur])][c];
    33             next[cur][c] = now;
    34         }
    35         last = next[cur][c];
    36         cnt[last]++;
    37     }
    38     void count() {
    39         for(int i = tot - 1; i > 1; --i)
    40             cnt[fail[i]] += cnt[i];
    41     }
    42 } PT;
    43 char str[maxn];
    44 int main() {
    45     while(~scanf("%s",str)) {
    46         PT.init();
    47         for(int i = 0; str[i]; ++i) PT.add(str[i]);
    48         PT.count();
    49         LL ret = 0;
    50         for(int i = 2; i < PT.tot; ++i)
    51             ret = max(ret,(LL)PT.len[i]*PT.cnt[i]);
    52         printf("%lld
    ",ret);
    53     }
    54     return 0;
    55 }
    View Code
  • 相关阅读:
    ubuntu與win7雙系統引導的默認系統問題
    Mac正确删除应用程序的方法
    latex链接外部文件
    ubuntu安装sunjava6
    String.Index 和 String.Split的用法例子
    关于数组传递以及ref,out的例子
    通过XElement查询XML的几种方法
    递归的基本例子
    frame与iframe的区别
    C#数组的用法,out传递值的用法
  • 原文地址:https://www.cnblogs.com/crackpotisback/p/4752831.html
Copyright © 2011-2022 走看看