Harry And Biological Teacher 分块 + hash

http://acm.hdu.edu.cn/showproblem.php?pid=5069

首先判断suffix和prefix最长多少可以直接暴力枚举长度然后 + hash可以立马判断是否相等,复杂度O(lenstr)

现在知道总长度 <= 1e5,  magic = sqrt(lenstr)

那么,

如果长度是 <= magic的,最多1e5个询问,每次询问我暴力也是才1e5 * sqrt(1e5)的复杂度。

如果长度是 >= magic的,

第一个极端情况是有magic个不同的串,这样就可以有magic^2个不同的询问,但是这样每个串的长度最长是magic,这样暴力也是才magic * magic * magic  = 1e5 * sqrt(1e5)的复杂度。

第二个极端情况是只有2个串,每个串长度都很长,1e5 / 2 的长度,这样暴力一次就需要O(1e5)的复杂度了。但是如果这样的话,不同的询问就会很少,可以用个ans数组存起来,ans[a][b],这样总复杂度也是 <= 1e5 * sqrt(1e5)的复杂度。

所以总复杂度是nsqrtn

#include <bits/stdc++.h>
#define IOS ios::sync_with_stdio(false)
using namespace std;
#define inf (0x3f3f3f3f)
typedef long long int LL;
const int maxn = 1e5 + 20;
char str[maxn];
int po[maxn], suffix[maxn], prefix[maxn];
int be[maxn], en[maxn];
int n, q;
int ans[444][444];
int getAns(int one, int two) {
    for (int i = min(en[two] - be[two] + 1, en[one] - be[one] + 1); i >= 1; --i) {
        if (prefix[be[two] + i - 1] == suffix[en[one] - i + 1]) {
            return i;
        }
    }
    return 0;
}
int pos[maxn];
void work() {
    scanf("%d%d", &n, &q);
    int magic = (int)sqrt(n * 1.0);
    int to = 0;
    for (int i = 1; i <= n; ++i) {
        scanf("%s", str + en[i - 1] + 1);
        int len = strlen(str + en[i - 1] + 1);
        be[i] = en[i - 1] + 1, en[i] = en[i - 1] + len;
        prefix[be[i]] = str[be[i]];
        for (int j = be[i] + 1; j <= en[i]; ++j) {
            prefix[j] = prefix[j - 1] * 131 + str[j];
        }
        suffix[en[i]] = str[en[i]];
        for (int j = en[i] - 1; j >= be[i]; --j) {
            suffix[j] = str[j] * po[en[i] - j] + suffix[j + 1];
        }
        if (len > magic) {
            pos[i] = ++to;
        }
    }
//    printf("%s\n", str + 1);
//    for (int i = 1; i <= n; ++i) {
//        printf("%d %d\n", be[i], en[i]);
//    }
    for (int i = 1; i <= to; ++i) {
        for (int j = 1; j <= to; ++j) {
            ans[i][j] = -1;
        }
    }
    while (q--) {
        int one, two;
        scanf("%d%d", &one, &two);
        if (en[one] - be[one] + 1 <= magic || en[two] - be[two] + 1 <= magic) {
            printf("%d\n", getAns(one, two));
        } else {
            if (ans[pos[one]][pos[two]] == -1) {
                ans[pos[one]][pos[two]] = getAns(one, two);
            }
            printf("%d\n", ans[pos[one]][pos[two]]);
        }
    }
}
int main() {
#ifdef local
    freopen("data.txt", "r", stdin);
//    freopen("data.txt", "w", stdout);
#endif
    po[0] = 1;
    for (int i = 1; i <= maxn - 20; ++i) po[i] = po[i - 1] * 131;
    while (scanf("%d%d", &n, &q) > 0) work();
    return 0;
}
时间: 2024-10-06 16:40:21

Harry And Biological Teacher 分块 + hash的相关文章

hdu 5069 Harry And Biological Teacher

Harry And Biological Teacher Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 38    Accepted Submission(s): 6 Problem Description As we all know, Harry Porter learns magic at Hogwarts School. How

HDU 5056 Harry And Biological Teacher

链接:http://acm.hdu.edu.cn/showproblem.php?pid=5069 题意:给出n个串,m个询问,每个询问(u,v),求u的一个最长后缀是v的前缀. 思路:离线.将关于u的后缀的查询放在一起,然后将u插入后缀自动机.对于每个v跑一遍即可. struct SAM { SAM *son[4],*pre; int len; int ok; void init() { clr(son,0); pre=0; ok=0; } }; SAM sam[N],*head,*last;

HDU 5069 Harry And Biological Teacher(AC自动机+线段树)

题意 给定 \(n\) 个字符串,\(m\) 个询问,每次询问 \(a\) 字符串的后缀和 \(b\) 字符串的前缀最多能匹配多长. \(1\leq n,m \leq 10^5\) 思路 多串匹配,考虑 \(\text{AC}\)自动机,对 \(n\) 个串建自动机,观察这个结构,不难发现 \(Trie\) 树的结构和前缀有关,\(fail\) 树的结构和后缀有关. 考虑离线,对于每个 \(b\) ,存储它对应的 \(a\) ,我们通过在自动机上扫 \(b\) 来回答.由于扫到某节点 \(u\)

BestCoder Round #14

Harry And Physical Teacher Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 38    Accepted Submission(s): 34 Problem Description As we all know, Harry Porter learns magic at Hogwarts School. How

Memcached哈希性能优化(八)——总结报告

转自:http://m.blog.csdn.net/blog/hzwfz1989/39120005 Memcached哈希性能优化报告 一. Memcached分析 这两个月一直在memcached优化和找工作之间忙着,一边复习一边优化改代码还真是个让人觉得难以忘记的夏天.做这个项目确实收获了很多,不管是对Linux的系统的认识,还是对memcached的认识都比以前更近一步,另外后面由于添加分块hash,替换LRU算法和更改hash算法对源代码进行修改,一不小心就把原来的代码的测试改跪了,用g

部分系列题

当然是不齐的. JZP系列 JZPKIL       数论,反演,积性函数,伯努利数,(常数优化) JZPFAR     k-d树 JZPTAB    分块 hash sam[太可怕了 不会写] JZPLCM    三维偏序,可持久化线段树维护 JZPEXT     数位统计(常数优化) JZPGYZ     suffix array水过 JZPCIR      找规律(OEIS水过) JZPFOR  三维哈密尔顿回路统计[太可怕了 不会] JZPLIT   构造 JZPLIT2  优化异或方程

最全BAT算法面试100题:阿里、百度、腾讯、京东、美团、今日头条

第一:复杂度估算和排序算法(上)1) 时间复杂度和空间复杂度 2)认识对数器 3)冒泡排序 4)选择排序 5)插入排序 6)如何分析递归过程的时间复杂度 7)归并排序 8)小和问题 第二:复杂度估算和排序算法(下)1)荷兰国旗问题 2)随机快速排序 3)堆结构与堆排序 4)认识排序算法的稳定性 5)认识比较器 6)桶排序 7)计数排序 8)基数排序 9)数组排序后的最大差值问题 10)排序算法在工程中的应用 第三:章栈.队列.链表.数组和矩阵结构1)栈结构 2)队列结构 3)链表结构 4)数组结

[JSOI2017]原力(分块+map(hash))

题目描述 一个原力网络可以看成是一个可能存在重边但没有自环的无向图.每条边有一种属性和一个权值.属性可能是R.G.B三种当中的一种,代表这条边上 原力的类型.权值是一个正整数,代表这条边上的原力强度.原力技术的核心在于将R.G.B三种不同的原力融合在一起产生单一的.便于利用的原力.为了评估 一个能源网络,JYY需要找到所有满足要求的三元环(首尾相接的三条边),其中R.G.B三种边各一条.一个三元环产生的能量是其中三条边的权值之积. 现在对于给出的原力网络,JYY想知道这个网络的总能量是多少.网络

UVA 1397 - The Teacher&#39;s Side of Math(高斯消元)

UVA 1397 - The Teacher's Side of Math 题目链接 题意:给定一个x=a1/m+b1/n,求原方程组 思路:由于m*n最多20,所有最高项只有20,然后可以把每个此项拆分,之后得到n种不同无理数,每一项为0,就可以设系数为变元,构造方程进行高斯消元 一开始用longlong爆了,换成分数写法也爆了,又不想改高精度,最后是机智的用了double型过的,不过用double精度问题,所以高斯消元的姿势要正确,并且最后输出要注意-0的情况 代码: #include <c