• Codeforces 1090J Two Prefixes


    Two Prefixes

    在纸上画了画感受一下可以感觉和循环节有关, 我们把每个可以表示的串写成 pre_a_i + pre_b_j的形式, 

    我们使得每个串在 i 最大的时候被统计到, 那么我们考虑答案为n * m - 重复的串个数,

    对于pre_a_i + pre_b_j 这个串, 我们记b[0] - b[ j ] 的循环节是k, 它被重复算了当且仅当,

    对于a[ 0 ] - a[ i ] 这个串存在一个长度为k的后缀和循环节相同。 

    那么我们枚举pre_a_i, 记L为a[ i + 1 ] 开始的串与b串的lcp, cnt[ i ] 为b的前缀中循环节小于等于 i 的个数,

    那么对于当前的pre_a_i多算的个数为cnt[L], 减掉就好了。

    #include<bits/stdc++.h>
    #define LL long long
    #define ull unsigned long long
    using namespace std;
    
    const int N = (int)1e5 + 7;
    
    int n, m;
    char s[N], t[N];
    int cnt[N];
    int f[N];
    
    vector<int> Zalgo(string &s) {
        vector<int> v(1, s.size());
        for(int i = 1, l = -1, r = -1; i < s.size(); i++) {
            if(i <= r && v[i - l] < r - i + 1) v.push_back(v[i - l]);
            else {
                l = i; r = (i > r) ? i : (r + 1);
                while(r < s.size() && s[r - i] == s[r]) r++;
                v.push_back((r--) - l);
            }
        }
        v.push_back(0);
        return v;
    }
    
    void getNext(char *s, int n) {
        f[0] = 0; f[1] = 0;
        for(int i = 1; i < n; i++) {
            int j = f[i];
            while(j && s[i] != s[j]) j = f[j];
            f[i + 1] = (s[i] == s[j] ? j + 1 : 0);
        }
        for(int i = 2; i <= n; i++) {
            if(f[i] > 0) cnt[i - f[i]]++;
        }
    }
    
    int main() {
        scanf("%s%s", s + 1, t + 1);
        n = strlen(s + 1);
        m = strlen(t + 1);
        getNext(t + 1, m);
        for(int i = 1; i <= m; i++) cnt[i] += cnt[i - 1];
    
        string S;
        for(int i = 1; i <= m; i++) S.push_back(t[i]);
        S.push_back('$');
        for(int i = 1; i <= n; i++) S.push_back(s[i]);
        vector<int> lcp = Zalgo(S);
    
        LL ans =  1LL * n * m;
        for(int i = 2; i <= n; i++) {
            ans -= cnt[lcp[i + m]];
        }
        printf("%lld
    ", ans);
        return 0;
    }
    
    /*
    */
  • 相关阅读:
    assign()与create()的区别
    ES6对象扩展——部分新的方法和属性
    ES6对象扩展——扩展运算符
    rest operater剩余操作符
    深拷贝和浅拷贝
    for in和for of的简单区别
    查询ES6兼容的网站
    ES6扩展——对象的扩展(简洁表示法与属性名表达式)
    滚动条设置样式
    marquee横向无缝滚动无js
  • 原文地址:https://www.cnblogs.com/CJLHY/p/11716569.html
Copyright © 2020-2023  润新知