zoukankan      html  css  js  c++  java
  • 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
    ", str + 1);
    //    for (int i = 1; i <= n; ++i) {
    //        printf("%d %d
    ", 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
    ", getAns(one, two));
            } else {
                if (ans[pos[one]][pos[two]] == -1) {
                    ans[pos[one]][pos[two]] = getAns(one, two);
                }
                printf("%d
    ", 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;
    }

    https://www.nowcoder.com/acm/contest/94/E

    #include <bits/stdc++.h>
    #define IOS ios::sync_with_stdio(false)
    using namespace std;
    #define inf (0x3f3f3f3f)
    typedef unsigned long long int LL;
    const int maxn = 1e6 + 20;
    char str[maxn];
    LL po[maxn], suffix[maxn], prefix[maxn];
    int be[maxn], en[maxn];
    int n, q;
    int ans[1000][1000];
    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() {
        int magic = (int)sqrt(300000 * 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
    ", str + 1);
    //    for (int i = 1; i <= n; ++i) {
    //        printf("%d %d
    ", be[i], en[i]);
    //    }
        for (int i = 1; i <= to; ++i) {
            for (int j = 1; j <= to; ++j) {
                ans[i][j] = -1;
            }
        }
        cin >> q;
        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
    ", getAns(one, two));
            } else {
                if (ans[pos[one]][pos[two]] == -1) {
                    ans[pos[one]][pos[two]] = getAns(one, two);
                }
                printf("%d
    ", 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", &n) > 0) work();
        return 0;
    }
  • 相关阅读:
    豆瓣最佳影评-星级转换
    佛山链家-bs修改网页代码难题-待突破
    爬取学校官网新闻-bs与xpath的恩怨情仇
    猫眼电影评论(1366错误)-版本一
    books新手实践xpath
    scrapy项目入门--shell的使用!
    selenium模拟浏览器进行百度搜索
    在VM中安装CentOs后无法切换到root用户
    VMware安装Linux虚拟机(手动划分分区)(CentOS为例)详细图解
    JDBC连接数据库 mysql serverTimezone 时差问题
  • 原文地址:https://www.cnblogs.com/liuweimingcprogram/p/7287708.html
Copyright © 2011-2022 走看看