zoukankan      html  css  js  c++  java
  • BZOJ_1212_[HNOI2004]L语言_哈希

    BZOJ_1212_[HNOI2004]L语言_哈希

    Description

    标点符号的出现晚于文字的出现,所以以前的语言都是没有标点的。现在你要处理的就是一段没有标点的文章。 一段文章T是由若干小写字母构成。一个单词W也是由若干小写字母构成。一个字典D是若干个单词的集合。 我们称一段文章T在某个字典D下是可以被理解的,是指如果文章T可以被分成若干部分,且每一个部分都是字典D中的单词。 例如字典D中包括单词{‘is’, ‘name’, ‘what’, ‘your’},则文章‘whatisyourname’是在字典D下可以被理解的 因为它可以分成4个单词:‘what’, ‘is’, ‘your’, ‘name’,且每个单词都属于字典D,而文章‘whatisyouname’ 在字典D下不能被理解,但可以在字典D’=D+{‘you’}下被理解。这段文章的一个前缀‘whatis’,也可以在字典D下被理解 而且是在字典D下能够被理解的最长的前缀。 给定一个字典D,你的程序需要判断若干段文章在字典D下是否能够被理解。 并给出其在字典D下能够被理解的最长前缀的位置。

    Input

    输入文件第一行是两个正整数n和m,表示字典D中有n个单词,且有m段文章需要被处理。 之后的n行每行描述一个单词,再之后的m行每行描述一段文章。 其中1<=n, m<=20,每个单词长度不超过10,每段文章长度不超过1M。

    Output

    对于输入的每一段文章,你需要输出这段文章在字典D可以被理解的最长前缀的位置。

    Sample Input

    4 3
    is
    name
    what
    your
    whatisyourname
    whatisyouname
    whaisyourname

    Sample Output

    14
    6
    0 整段文章’whatisyourname’都能被理解
    前缀’whatis’能够被理解
    没有任何前缀能够被理解

    分析:

    考虑DP,f[i]表示前i个字符是否能被理解。

    f[i] |= f[j](j+1 ~ i这段字符是否出现在字典里)

    然后我们哈希一下O(nm)搞过去了

    代码:

    #include <stdio.h>
    #include <string.h>
    #include <algorithm>
    using namespace std;
    #define N 1000050
    #define LL unsigned long long
    LL p = 19260817, h[N], d[22], mi[N];
    int len[22], n, m;
    int ok[N];
    char word[22], s[N];
    int main() {
        scanf("%d%d",&n,&m);
        register int i, j, k, o;
        for(i = 1;i <= n; ++ i) {
            scanf("%s", word + 1);
            len[i] = strlen(word + 1);
            for(j = 1;j <= len[i]; ++ j) {
                d[i] = d[i] * p + word[j];
            }
        }
        for(mi[0] = 1, i = 1;i <= 10; ++ i) {
            mi[i] = mi[i - 1] * p;
        }
        for(o = 1;o <= m; ++ o) {
            scanf("%s", s + 1);
            int l = strlen(s + 1), ans = 0;
            for(ok[0] = o, i = 1;i <= l; ++ i) {
                h[i] = h[i - 1] * p + s[i];
                for(j = 1;j <= n;++ j) {
                    k = i - len[j] + 1;
                    if(k <= 0 || ok[k - 1] != o) continue;
                    if(d[j] == h[i] - h[k - 1] * mi[len[j]]) {
                        ok[i] = o; ans = i; break;
                    }
                }
            }
            printf("%d
    ",ans);
        }
    }
    
  • 相关阅读:
    Java实现 蓝桥杯VIP 算法提高 排队打水问题
    Java实现 蓝桥杯VIP 算法提高 排队打水问题
    Java实现 蓝桥杯VIP 算法提高 排队打水问题
    Java实现 蓝桥杯VIP 算法提高 特殊的质数肋骨
    Java实现 蓝桥杯VIP 算法提高 特殊的质数肋骨
    Java实现 蓝桥杯VIP 算法提高 特殊的质数肋骨
    Java实现 蓝桥杯VIP 算法提高 特殊的质数肋骨
    现在使用控件, 更喜欢继承(覆盖控件已有的函数,很奇怪的一种使用方式)
    Controls 属性与继承 TShape 类的小练习(使用TShape可以解决很多图形问题)
    QT创建窗口程序、消息循环和WinMain函数(为主线程建立了一个QEventLoop,并执行exec函数)
  • 原文地址:https://www.cnblogs.com/suika/p/8672167.html
Copyright © 2011-2022 走看看