zoukankan      html  css  js  c++  java
  • D. Tavas and Malekas DFS模拟 + kmp + hash || kmp + hash

    http://codeforces.com/contest/535/problem/D

    如果真的要把m个串覆盖上一个串上面,是可以得,不会超时。

    要注意到一点,全部覆盖后再判断时候合法,和边放边判断,结果是一样的,后者还更难做到。

    那么就是先按顺序把串覆盖上去,已经存在的就不去覆盖了,然后kmp一次记录匹配位置,判断即可。

    用DFS覆盖,DFS回溯的时候记录一个数组tonext[i]表示第i个点的第一个空位是tonext[i],这样覆盖上去就是O(n)

    #include <cstdio>
    #include <cstdlib>
    #include <cstring>
    #include <cmath>
    #include <algorithm>
    #include <assert.h>
    #define IOS ios::sync_with_stdio(false)
    using namespace std;
    #define inf (0x3f3f3f3f)
    typedef long long int LL;
    
    
    #include <iostream>
    #include <sstream>
    #include <vector>
    #include <set>
    #include <map>
    #include <queue>
    #include <string>
    const int maxn = 1e6 + 20;
    const int MOD = 1e9 + 7;
    int tonext[maxn];
    int ret;
    char str[maxn];
    char sub[maxn];
    void dfs(int cur, int k, int from) {
        if (k < 0) return;
        if (k == 0) {
            ret = cur;
            return;
        }
        if (tonext[cur] != cur) {
            ret = tonext[cur];
            dfs(tonext[cur], k - (tonext[cur] - cur), from + tonext[cur] - cur);
            tonext[cur] = ret;
        } else {
            ret = cur + 1;
            str[cur] = sub[from];
            dfs(cur + 1, k - 1, from + 1);
            tonext[cur] = ret;
        }
    }
    int a[maxn];
    bool HASH[maxn];
    int kmpnext[maxn];
    void get_next(char sub[], int lensub) {
        int i = 1, j = 0;
        kmpnext[1] = 0;
        while (i <= lensub) {
            if (j == 0 || sub[i] == sub[j]) {
                kmpnext[++i] = ++j;
            } else j = kmpnext[j];
        }
        return;
    }
    void kmp(int lenstr, int lensub) {
        int i = 1, j = 1;
        while (i <= lenstr) {
            if (j == 0 || str[i] == sub[j]) {
                ++i;
                ++j;
            } else j = kmpnext[j];
            if (j == lensub + 1) {
                HASH[i - lensub] = true;
                j = kmpnext[j];
            }
        }
        return;
    }
    void work() {
        int lenstr, m;
        scanf("%d%d", &lenstr, &m);
        for (int i = 1; i <= lenstr; ++i) {
            tonext[i] = i;
            str[i] = 'A';
    //        printf("f");
        }
    //    printf("%c
    ", str[1]);
        scanf("%s", sub + 1);
        int lensub = strlen(sub + 1);
        for (int i = 1; i <= m; ++i) {
            scanf("%d", &a[i]);
            dfs(a[i], lensub, 1);
        }
        str[lenstr + 1] = '';
    //    printf("%s
    ", str + 1);
        get_next(sub, lensub);
        kmp(lenstr, lensub);
        for (int i = 1; i <= m; ++i) {
            if (!HASH[a[i]]) {
                cout << 0 << endl;
                return;
            }
        }
        LL ans = 1;
        for (int i = 1; i <= lenstr; ++i) {
            if (str[i] == 'A') {
                ans *= 26;
                if (ans >= MOD) ans %= MOD;
            }
        }
        cout << ans << endl;
    }
    
    int main() {
    #ifdef local
        freopen("data.txt", "r", stdin);
    //    freopen("data.txt", "w", stdout);
    #endif
        work();
        return 0;
    }
    View Code

    开始的时候想不到直接kmp

    用的其实就是kmp的next数组,不断next[next[]]

    就是记录所有的前缀和后缀相等。

    对于abc****abc,也就是前后缀相等的话,长度是3

    记上一个覆盖到的位置是pos[i - 1] + lensub - 1

    然后如果这个和他没交集,就算,如果有,要判断。怎么判断呢?

    算出交集大小,如果交集刚好是3,那么是可以得。否则,是NO

    交集是3说明后缀的那3个和前缀匹配了。

    注意m可能是0

    #include <cstdio>
    #include <cstdlib>
    #include <cstring>
    #include <cmath>
    #include <algorithm>
    #include <assert.h>
    #define IOS ios::sync_with_stdio(false)
    using namespace std;
    #define inf (0x3f3f3f3f)
    typedef long long int LL;
    
    
    #include <iostream>
    #include <sstream>
    #include <vector>
    #include <set>
    #include <map>
    #include <queue>
    #include <string>
    const int maxn = 1e6 + 20;
    const int MOD = 1e9 + 7;
    char sub[maxn];
    int tonext[maxn];
    int pos[maxn];
    bool book[maxn];
    void get_next(char sub[], int lensub) {
        int i = 1, j = 0;
        tonext[1] = 0;
        while (i <= lensub) {
            if (j == 0 || sub[i] == sub[j]) {
                tonext[++i] = ++j;
            } else j = tonext[j];
        }
        return;
    }
    void work() {
        int lenstr, m;
    //    cin >> lenstr >> m;
    //    cin >> sub + 1;
        scanf("%d%d", &lenstr, &m);
        scanf("%s", sub + 1);
        int lensub = strlen(sub + 1);
        get_next(sub, lensub);
        for (int i = 1; i <= m; ++i) {
    //        cin >> pos[i];
            scanf("%d", &pos[i]);
        }
        int t = tonext[lensub + 1];
        while (t != 1) {
            book[t - 1] = true;
            t = tonext[t];
        }
        int total = lenstr - lensub;
        if (m == 0) {
            total += lensub;
        }
        for (int i = 2; i <= m; ++i) {
            int to = pos[i - 1] + lensub - 1;
            int haha = to - pos[i] + 1;
            if (haha <= 0) {
                total -= lensub;
                continue;
            }
            if (!book[haha]) {
                printf("0
    ");
                return;
            }
            total -= lensub - haha;
        }
        LL ans = 1;
        for (int i = 1; i <= total; ++i) {
            ans *= 26;
            if (ans >= MOD) ans %= MOD;
        }
        printf("%I64d
    ", ans);
    }
    
    int main() {
    #ifdef local
        freopen("data.txt", "r", stdin);
    //    freopen("data.txt", "w", stdout);
    #endif
        work();
        return 0;
    }
    View Code
  • 相关阅读:
    MDX Step by Step 读书笔记(六) Building Complex Sets (复杂集合的处理) Filtering Sets
    在 Visual Studio 2012 开发 SSIS,SSAS,SSRS BI 项目
    微软BI 之SSIS 系列 在 SSIS 中读取 SharePoint List
    MDX Step by Step 读书笔记(五) Working with Expressions (MDX 表达式) Infinite Recursion 和 SOLVE_ORDER 原理解析
    MDX Step by Step 读书笔记(五) Working with Expressions (MDX 表达式)
    使用 SQL Server 2012 Analysis Services Tabular Mode 表格建模 图文教程
    MDX Step by Step 读书笔记(四) Working with Sets (使用集合) Limiting Set and AutoExists
    SQL Server 2012 Analysis Services Tabular Model 读书笔记
    Microsoft SQL Server 2008 MDX Step by Step 学习笔记连载目录
    2011新的开始,介绍一下AgileEAS.NET平台在新的一年中的发展方向
  • 原文地址:https://www.cnblogs.com/liuweimingcprogram/p/6145139.html
Copyright © 2011-2022 走看看