关闭

[BZOJ 3654] 图样图森破

标签: BZOJ后缀数组记忆化搜索
789人阅读 评论(0) 收藏 举报

这里写图片描述

Solution :
把每个串和它们的反转拉一起求一个后缀数组,然后枚举回文串的中心,往回文串两边尽可能添加串,这个过程可以记忆化,如果转移中发现了环说明长度可以无限大。

吐槽:刚开始写的RMQ有点问题,怒改为暴力求lcp然后就A了…10s…..这题好 但是数据有待加强…….

#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <bitset>
#include <cmath>
#include <ctime>
#include <algorithm>
#include <iterator>
#include <vector>
#include <queue>
#include <set>
#include <map>

#define rep(i, x, y) for (int i = (x), _ = (y); i <= _; ++i)
#define down(i, x, y) for (int i = (x), _ = (y); i >= _; --i)
#define x first
#define y second
#define LX_JUDGE

using namespace std;
typedef long long LL;

template<typename T> inline void upMax(T & x, T y) { x < y ? x = y : 0; }
template<typename T> inline void upMin(T & x, T y) { x > y ? x = y : 0; }

template<typename T>
inline void read(T & x)
{
    char c;
    while ((c = getchar()) < '0' || c > '9') ;
    for (x = c - '0'; (c = getchar()) >= '0' && c <= '9'; x = x * 10 + c - '0') ;
}

const LL inf = 1e15;
const int N = 2e5 + 3e4;

namespace suffixArray
{
    int Sa[N], Rank[N], height[N];
    int mn[N][19], Log[N], tot;

    void suffixDa(char * r, int n, int m)
    {
        static int ws[N];
        int i, j, p, *x = Rank, *y = height;
        tot = n;

        memset(ws, 0, sizeof(int) * m);
        for (i = 0; i < n; ++i)
            ++ws[x[i] = r[i]];
        for (i = 1; i < m; ++i)
            ws[i] += ws[i - 1];
        for (i = n - 1; ~i; --i)
            Sa[--ws[x[i]]] = i;
        for (j = p = 1; p < n; j <<= 1, m = p)
        {
            for (p = 0, i = n - j; i < n; ++i)
                y[p++] = i;
            for (i = 0; i < n; ++i) if (Sa[i] >= j)
                y[p++] = Sa[i] - j;
            memset(ws, 0, sizeof(int) * m);
            for (i = 0; i < n; ++i)
                ++ws[x[i]];
            for (i = 1; i < m; ++i)
                ws[i] += ws[i - 1];
            for (i = n - 1; ~i; --i)
                Sa[--ws[x[y[i]]]] = y[i];
            swap(x, y);
            x[Sa[0]] = 0, p = 1;
            for (i = 1; i < n; ++i)
                x[Sa[i]] = (y[Sa[i - 1]] == y[Sa[i]] && y[Sa[i - 1] + j] == y[Sa[i] + j]) ? p - 1 : p++;
        }
        for (i = 0; i < n; ++i)
            Rank[Sa[i]] = i;
        for (i = p = 0; i < n - 1; ++i)
        {
            p ? --p : 0;
            j = Sa[Rank[i] - 1];
            while (r[i + p] == r[j + p]) 
                ++p;
            height[Rank[i]] = p;
        }
        height[0] = height[1] = height[n] = 0;

        rep (i, 2, n)
            Log[i] = Log[i >> 1] + 1;

        rep (i, 0, n - 1) 
            mn[i][0] = height[i];

        rep (i, 0, Log[n] - 1)
        {
            rep (j, 0, n - (1 << (i + 1)) + 1)
                mn[j][i + 1] = min(mn[j][i], mn[j + (1 << i)][i]);
        }
    }

    int Lcp(int x, int y)
    {
        if (x == y)
            return tot - x;
        x = Rank[x], y = Rank[y];
        if (x > y)
            swap(x, y);
        int k = Log[y - x];
        return min(mn[x + 1][k], mn[y - (1 << k) + 1][k]);
    }
}

char str[N];
int belong[N], start[211], last[211];
int n, m;

LL f[N];
bool ins[N];

LL calc(int x)
{
    using suffixArray::Lcp;

    if (str[x] < 'a')
        x = m;

    if (ins[x]) 
        return inf;
    else if (f[x] > 0) 
        return f[x];

    LL &ans = f[x];
    ins[x] = 1;

    if (x == m)
    {
        rep (i, 1, n + n)
            upMax(ans, calc(start[i]));
    }
    else 
    {
        int p = belong[x];

        rep (j, (p <= n ? n + 1 : 1), (p <= n ? n + n : n))
        {
            int t = min(Lcp(x, start[j]), min(last[p] - x, last[j] - start[j]));
            if (x + t == last[p])
                upMax(ans, calc(start[j] + t) + t * 2);
            else if (start[j] + t == last[j])
                upMax(ans, calc(x + t) + t * 2);
            else 
                upMax(ans, 2ll * t);
        }
    }

    upMax(ans, 0ll), upMin(ans, inf);
    ins[x] = 0;

    return ans;
}

int main()
{
#ifdef LX_JUDGE
    freopen("in.txt", "r", stdin);
#endif
    read(n);

    rep (i, 1, n)
    {
        scanf("%s", str + m);
        start[i] = m;
        while (str[m])
            belong[m++] = i;
        last[i] = m;
        str[m++] = 'a' - 1;
    }

    int cur = 0;

    rep (i, n + 1, n + n)
    {
        start[i] = m;
        while (str[cur] >= 'a')
        {
            belong[m] = i;
            str[m++] = str[cur++];
        }
        last[i] = m;
        str[m++] = str[cur++];
        reverse(str + start[i], str + last[i]);
    }

    str[m++] = 0;
    suffixArray::suffixDa(str, m, 128);

    memset(f, -1, sizeof(f));

    LL ans = calc(m);

    rep (i, 1, n)
    {
        using suffixArray::Lcp;
        for (int j = start[i], k = last[i + n] - 1; j < last[i]; ++j, --k)
        {
            int tmp = min(Lcp(j, k), min(last[i] - j, last[i + n] - k));

            if (j + tmp == last[i])
                upMax(ans, calc(k + tmp) + 2 * tmp - 1);
            else if (k + tmp == last[i + n])
                upMax(ans, calc(j + tmp) + 2 * tmp - 1);
            else 
                upMax(ans, 2ll * tmp - 1);
        }
        for (int j = start[i] + 1, k = last[i + n] - 1; j < last[i]; ++j, --k)
        {
            int tmp = min(Lcp(j, k), min(last[i] - j, last[i + n] - k));

            if (j + tmp == last[i])
                upMax(ans, calc(k + tmp) + tmp * 2);
            else if (k + tmp == last[i + n])
                upMax(ans, calc(j + tmp) + tmp * 2);
            else 
                upMax(ans, 2ll * tmp);
        }
    }

    ans < inf ? printf("%lld\n", ans) : puts("Infinity");

    return 0;
}
0
0
查看评论

【BZOJ3654】图样图森破【最长路】【后缀数组】【ST表】【回文串】【LCP】

【题目链接】 有一个结论:如果答案不是Infinity,那么最长回文子串只可能出现在一个串里,或者两个串拼接一次形成的串里。 那么我们枚举每个串的每个回文中心,对于剩下的不在回文串里的子串,去其他串里找一个拼接串,看能不能形成更大的回文串。 于是我们需要一个快速查询LCP的数据结构,选择后缀数...
  • BraketBN
  • BraketBN
  • 2016-05-03 11:55
  • 825

图样图森破:认识WiFi以后

今天跟朋友聊天,他跟我说,qq被盗了,一直被盗,自己总是被迫下线,改了密码还是不行。   话说问我我怎么会知道呢?八过,鉴于朋友总是喜欢连外面的免费WiFi,我很快就问出具体是什么情况了。但是我不会怎么才能让qq不被盗啊!     朋友喜欢在公共场合连免费WiFi,大部分是因为自己的...
  • u014515790
  • u014515790
  • 2014-07-24 17:18
  • 367

[未完待续][NOI2017模拟]图样图森破

题目背景 2016.05.19 T3题目描述 长者有一个字符串集合 S ,此处集合的概念与数学中的集合不同,其中可以含有重复的元素。初始时 S 包含 n 个字符串 s1,s2,…,sn。有下面两种操作: 向 S 中加入一个已经存在于 S 中的字符串。 从 S 中选出两个字符串,将这两个字符串...
  • g19zwk
  • g19zwk
  • 2017-07-21 13:29
  • 204

[bzoj4770]图样

题目描述小火车励志成为一名辣鸡出题人,但是要成为一名辣鸡出题人,代码必须跑得比谁都快,这样就能把他们都卡常数 了!为了锻炼自己,他找到了一位长者–乐滋滋,乐滋滋说:”你啊,tooyoung!西方的哪一个国家我没有去过?” 小火车坐在高高的骨灰旁边,听长者讲那西方的事情。西方有n个国家,长者决定向...
  • WerKeyTom_FTD
  • WerKeyTom_FTD
  • 2017-03-19 16:57
  • 402

告诉我图样图森破的两道简单C++笔试题

明明两道很简单的题目,但是因为不细(zhi)心(dao),就错了。 Too young too simple~╮(╯▽╰)╭
  • u011044759
  • u011044759
  • 2014-08-31 22:55
  • 2340

ZUFE 2017院赛 - Problem M: 图样图森破(树状数组)

由最后一句话可知,这个图为一个环。 那么用树状数组保存每一条边的值,然后每一次询问找u到v的总值就行,然后和取反比较(即总长度减去这个值,就是另一个方向的)。输出比较大的。 更改值也容易。 先处理一下每个点的位置,毕竟1 2 3 4 不一定连接在一起。 我的算法对n=1,n=2会有问题,所以...
  • Mr_Treeeee
  • Mr_Treeeee
  • 2017-12-10 22:45
  • 206

2017图森未来杯(中学虐大学杯)D题

题目: Let's Chat Time Limit: 1 Second      Memory Limit: 65536 KB ACM (ACMers' Chatting Messenger) is a famous...
  • winnerCLAY
  • winnerCLAY
  • 2017-04-23 12:23
  • 522

Deep learning for arts——王乃岩(图森科技)

主持人刘劲扬:下面首先请王乃岩老师给我们做关于“深度学习的艺术应用”,这两天我们看了,好像画画的那例子。      王乃岩:大家好!我叫王乃岩,来自图森科技,非常荣幸能在这里和大家交流一下“深度学习在艺术领域的一些应用”。因为艺术领域一直被...
  • baobei0112
  • baobei0112
  • 2016-06-14 09:18
  • 2603

图森未来杯(中学虐大学杯)E题,数位DP

先声明一下,我是看了大牛博客后才知道怎么写的,文章末尾会给出大牛博客链接 Seven Segment Display Time Limit: 2 Seconds      Memory Limit: 65536 KB A seven seg...
  • winnerCLAY
  • winnerCLAY
  • 2017-04-24 19:53
  • 302

图森未来C轮融资5500万美元,新浪继续跟投,无人卡车公开试乘

李根 发自 凹非寺  量子位 报道 | 公众号 QbitAI 无人车公司图森未来(TuSimple),又完成了新一轮融资。 C轮,5500万美元,复合资本领投,老股东新浪、治平资本跟投。图森未来CEO陈默表示,本轮融资将被用于进一步的研发和路测当中。 11月初,...
  • yH0VLDe8VG8ep9VGe
  • yH0VLDe8VG8ep9VGe
  • 2017-11-21 00:00
  • 115
    个人资料
    • 访问:39081次
    • 积分:700
    • 等级:
    • 排名:千里之外
    • 原创:29篇
    • 转载:0篇
    • 译文:1篇
    • 评论:13条
    文章分类
    最新评论