• cf1200 E Compress Words(哈希)


    题意

    有n个字符串,记为s1,s2……sn,s2与s1合并,合并的方式为:s1的后缀若与s2的前缀相同,就可以重叠起来,要最长的。

    举个例子:

    “1333”  “33345” → “133345”

    s1与s2合并后产生的字符串,再与s3合并,以此类推。

     

    思路

    两个字符串的子串匹配,比较容易想到哈希。

    一开始想的是从左往右哈希,就是:“123” → 123,但是这样哈希的话,若要更新字符串(就是在末尾添加字符),那么前面每个位置的哈希值都要变,复杂度爆炸。

    那就试试从右往左哈希,就是:“123” → 321,这样要在末尾添加字符的时候,前面的哈希值不会变,很好更新。

    然后,我们就可以记录当前字符串的最后一个字符是什么,然后遍历下一个要合并进来的字符串,当遇到和末尾相同的字符时,就可以哈希看看能否匹配。

    代码

    #include <stdio.h>
    #include <queue>
    #include <string>
    #include <string.h>
    #include <algorithm>
    #include <math.h>
    using namespace std;
    typedef long long int ll;
    const int maxn = 1e6 + 10;
    const ll inf = 0x3f3f3f3f;
    const ll mod = 1e9 + 7;
    const ll seed = 131;
    char s[maxn],t[maxn];
    ll sval[maxn],tval[maxn],fac[maxn];
    int main()
    {
        int n,lens,lent;
        char tail;
        fac[0] = 1;
        for(int i = 1;i < maxn;i++){
            fac[i] = (fac[i - 1] * seed) % mod;
        }
        while(scanf("%d",&n) != EOF){
            scanf("%s",s + 1);
            lens = strlen(s + 1);
            sval[0] = 0;
            for(int i = 1;i <= lens;i++){
                sval[i] = (((s[i] - '0') * fac[i - 1]) % mod + sval[i - 1]) % mod;
            }
            tail = s[lens];
            n--;
            ll now = 0,pos = 0;
            while(n--){
                now = pos = 0;
                scanf("%s",t + 1);
                lent = strlen(t + 1);
                for(int i = 1;i <= lent;i++){
                    if(i > lens)
                        break;
                    now = (((t[i] - '0') * fac[i - 1]) % mod + now) % mod;
                    if(t[i] == tail){
                        if((now * fac[lens - i]) % mod == ((sval[lens] - sval[lens - i]) % mod + mod) % mod){
                            pos = i;
                        }
                    }
                }
    
                for(int i = pos + 1;i <= lent;i++){
                    sval[lens + 1] = (((t[i] - '0') * fac[lens]) % mod + sval[lens]) % mod;
                    lens++;
                    s[lens] = t[i];
                }
                tail = s[lens];
            }
            s[lens + 1] = 0;
            printf("%s
    ",s + 1);
        }
        return 0;
    }
  • 相关阅读:
    @hdu
    @51nod
    @51nod
    @51nod
    JS-正则表达式常规运用
    CSS-复选框默认样式修改
    Vue-路由传参query与params
    Vue-阻止页面回退
    Vue-表单提交
    JS-原生的ajax
  • 原文地址:https://www.cnblogs.com/InitRain/p/12299138.html
Copyright © 2020-2023  润新知