• 回文树入门


    回文串  HYSBZ - 3676

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

    建一颗回文树,然后getans统计答案就OK了.  (回文树见IOI2017论文)

    #include <cstdio>
    
    const int maxn = 300050;
    
    class pal {
    public:
        int next[maxn][26];
        int fail[maxn];
        int len[maxn];
        int cnt[maxn];
        char str[maxn];
        int last;
        int tot;
        int n;
        
        // 记录节点长度,同时返回一个节点 
        inline int node(int _len) {
            len[tot] = _len;
            return tot++;
        }
        
        // odd根初始化为: 长度为-1  even根初始化len为0
        // 同时str[0]设置为字符集没有的字符 用于判断.
        // even根的fail指针是odd根 odd根的fail指针是自身. 
        void init() {
            last = tot = n = 0;
            node(0); node(-1);
            str[0] = -1;  fail[0] = fail[1] = 1; 
        }
        
        // 获得添加字符后,可以组成回文串的位置. 
        inline int GetFail(int cur) {
            while (str[n-len[cur]-1] != str[n])
                cur = fail[cur];
            return cur;
        }
        
        // 添加新字符  
        void insert(char ch) {
            str[++n] = ch;  
            int cur = GetFail(last), now;
            if (!next[cur][ch]) {
                now = node(len[cur] + 2);
                fail[now] = next[GetFail(fail[cur])][ch]; //和下一句的顺序不能反 
                next[cur][ch] = now;
            }
            ++cnt[last = next[cur][ch]]; // 出现次数,但是不完全统计,还需要for来统计.(因为一个长的回文串可能会包含一些小的回文串.) 
        }
        
        long long getans() {
            int i;
            long long res = 0;
            for (i=tot-1; i; --i)      //  统计出现次数 
                cnt[fail[i]] += cnt[i];
            for (i=tot-1; i; --i) 
                if (res < 1ll*len[i]*cnt[i])
                    res = 1ll*len[i]*cnt[i];
            return res;        
        }
    }pal;
    
    
    char s[300050];
    
    int main() {
    //    freopen("E:\input.txt", "r", stdin);
        pal.init();
        scanf("%s", s);
        for (char *p=s; *p; p++) 
            pal.insert(*p - 'a');
        printf("%lld
    ", pal.getans());
        return 0;
    }
  • 相关阅读:
    今天学到的单词
    今天是运维的一天
    今天是属于数据库的一天
    Python基础9 元组的访问和拆包
    Python基础8 元组的创建
    Python基础7 序列
    Python基础6 控制语句 if else elif range() while for
    Python基础5 运算符
    Python基础4 字符串的查找 find rfind 字符串类型和数字类型的转换
    Python基础2 数据类型:数字类型
  • 原文地址:https://www.cnblogs.com/cgjh/p/9597551.html
Copyright © 2020-2023  润新知