zoukankan      html  css  js  c++  java
  • E. Compress Words(Hash,KMP)

    E. Compress Words
    time limit per test
    1 second
    memory limit per test
    256 megabytes
    input
    standard input
    output
    standard output

    Amugae has a sentence consisting of nn words. He want to compress this sentence into one word. Amugae doesn't like repetitions, so when he merges two words into one word, he removes the longest prefix of the second word that coincides with a suffix of the first word. For example, he merges "sample" and "please" into "samplease".

    Amugae will merge his sentence left to right (i.e. first merge the first two words, then merge the result with the third word and so on). Write a program that prints the compressed word after the merging process ends.

    Input

    The first line contains an integer nn (1n1051≤n≤105), the number of the words in Amugae's sentence.

    The second line contains nn words separated by single space. Each words is non-empty and consists of uppercase and lowercase English letters and digits ('A', 'B', ..., 'Z', 'a', 'b', ..., 'z', '0', '1', ..., '9'). The total length of the words does not exceed 106106.

    Output

    In the only line output the compressed word after the merging process ends as described in the problem.

    Examples
    input
    5
    I want to order pizza
    
    output
    Iwantorderpizza
    input
    5
    sample please ease in out
    
    output
    sampleaseinout

     算法:Hash 或者 KMP

    题解:首先分析题目,题目要求我们将每个连续单词相同的前后缀合并成一个,在我们学过的知识里面,字符串前后缀相同的匹配肯定第一想到的就是KMP,对,这题可以用KMP直接做,但是还有一种使代码更加简洁,思路更加简单的方法,那就是用Hash。只要每次查询的时候直接暴力求前后缀相同的最大字符数就行。

    Hash:

    #include <iostream>
    #include <cstdio>
    
    using namespace std;
    
    typedef long long ll;
    
    const int maxn = 1e5+7;
    const int mod = 999999998;
    const int base = 2333333;
    
    string ans, s;
    
    void solve() {
        ll hl = 0, hr = 0, tmp = 1, index = 0;
        for(int i = 0; i < (int)min(ans.size(), s.size()); i++) {
            hl = (hl * base + ans[ans.size() - i - 1]) % mod;   //获取左边数组的后缀Hash值
            hr = (s[i] * tmp + hr) % mod;       //获取右边数组的前缀Hash值
            tmp = (tmp * base) % mod;
            if(hl == hr) {
                index = i + 1;      //获取最大的字符匹配位数
            }
        }
        for(int i = index; i < (int)s.size(); i++) {
            ans += s[i];
        }
    }  
    
    int main() {
        int n;
        scanf("%d", &n);
        cin >> ans;
        for(int i = 1; i < n; i++) {
            cin >> s;
            solve();
        }
        cout << ans << endl;
        return 0;
    }
  • 相关阅读:
    (中等) HDU 1495 非常可乐,BFS。
    (简单) POJ 1562 Oil Deposits,BFS。
    (简单) POJ 3984 迷宫问题,BFS。
    动态规划(斐波那契系列)---爬楼梯
    回溯---N皇后
    回溯---数独
    回溯---分割字符串使得每个部分都是回文数
    回溯---含有相同元素求子集
    回溯---子集
    回溯---组合求和
  • 原文地址:https://www.cnblogs.com/buhuiflydepig/p/11340218.html
Copyright © 2011-2022 走看看