zoukankan      html  css  js  c++  java
  • Victor and String[Bestcoder #52 1004](回文树)

    题目描述

    Victor喜欢玩字符串。他认为一个字符串是迷人的,当且仅当字符串是回文的。
    Victor想玩n次。每次他都会做以下四种操作中的一种。
    操作1:在字符串的开头添加一个字符 c。
    操作2:在字符串的末尾添加一个字符 c。
    操作3:询问不同的迷人子字符串的数量。
    操作4:询问迷人子字符串的数量,必须计算从不同位置开始的相同子字符串的数量。
    在一开始Victor有一个空字符串。

    输入格式

    输入包含几个测试用例,最多5个用例。 在每个测试用例中,第一行一个整数n表示操作的数量。
    下面n行的第一个数字是整数op,表示操作的类型。如果op=1或2,后面会有一个小写的英文字母。

    输出格式

    对于每个查询操作(操作3或4),输出正确的答案。

    样例

    输入样例1

    6
    1 a
    1 b
    2 a
    2 c
    3
    4
    8
    1 a
    2 a
    2 a
    1 a
    3
    1 b
    3
    4
    

    输出样例2

    4
    5
    4
    5
    11

    这是一道模板题,直接上代码。

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    using namespace std;
    typedef long long ll;
    const int N = 400000;
    struct Plalindrome_Tree{
        int go[26], len, fail;
        ll fail_len;
    }pt[N];
    int pre, suf, tot;
    ll ans;
    int q;
    int l, r;
    char s[N];
    void init() {
        memset(s, -1, sizeof(s));
        memset(pt, 0, sizeof(pt));
        tot = ans = 0;
        pre = suf = 0;
        l = 200000;
        r = 199999;
    }
    void build() {
        pt[++tot].len = -1;
        pt[0].fail = pt[1].fail = 1;
        pt[0].fail_len = 2;
        pt[1].fail_len = 1;
    }
    void add_back(int c) {
        int p = suf;
        while (s[r - pt[p].len - 1] != s[r]) p = pt[p].fail;
        if (!pt[p].go[c]) {
            int v = ++tot, k = pt[p].fail;
            pt[v].len = pt[p].len + 2;
            while (s[r - pt[k].len - 1] != s[r]) k = pt[k].fail;
            pt[v].fail = pt[k].go[c];
            pt[v].fail_len = pt[pt[k].go[c]].fail_len + 1;
            pt[p].go[c] = v;
        }
        suf = pt[p].go[c];
    }
    void add_front(int c) {
        int p = pre;
        while (s[l + pt[p].len + 1] != s[l]) p = pt[p].fail;
        if (!pt[p].go[c]) {
            int v = ++tot, k = pt[p].fail;
            pt[v].len = pt[p].len + 2;
            while (s[l + pt[k].len + 1] != s[l]) k = pt[k].fail;
            pt[v].fail = pt[k].go[c];
            pt[v].fail_len = pt[pt[k].go[c]].fail_len + 1;
            pt[p].go[c] = v;
        }
        pre = pt[p].go[c];
    }
    int main() {
        while (cin >> q) {
            init();
            build();
            while (q--) {
                int opt;
                char ch;
                cin >> opt;
                switch (opt) {
                    case 1:
                        cin >> ch;
                        s[--l] = ch;
                        add_front(ch - 'a');
                        ans += pt[pre].fail_len - 2;
                        if (pt[pre].len == r - l + 1) suf = pre;
                        break;
                    case 2:
                        cin >> ch;
                        s[++r] = ch;
                        add_back(ch - 'a');
                        ans += pt[suf].fail_len - 2;
                        if (pt[suf].len == r - l + 1) pre = suf;
                        break;
                    case 3:
                        cout << tot - 1;
                        puts("");
                        break;
                    case 4:
                        cout << ans;
                        puts("");
                        break;
                    default:
                        puts("Wrong Input");
                        break;
                }
            }
    
        }
        return 0;
    }
  • 相关阅读:
    git报错:failed to push some refs to 'git@github.com:JiangXiaoLiang1988/CustomerHandl
    Form_通过Trace分析Concurrent和Form性能和异常详解(案例)
    PLSQL_Oracle Lock锁的处理(案例)
    Report_客制化报表输出Excel后去0问题(案例)
    DBA_Oracle DBA常用表汇总(概念)
    PLSQL_Oracle PLSQL处理日期方式大全(概念)
    PLSQL_Oracle PLSQL内置函数大全(概念)
    PLSQL_PLSQL中DML/DDL/DCL的概念和区分(概念)
    Shell_Oracle Erp基于主机文件Host开发详解(案例)
    Report_客制化以PLSQL输出HTML标记实现WEB报表(案例)
  • 原文地址:https://www.cnblogs.com/zcr-blog/p/12298888.html
Copyright © 2011-2022 走看看