ICode9

精准搜索请尝试: 精确搜索
首页 > 编程语言> 文章详细

福州大学第十六届程序设计竞赛

2021-05-02 22:05:46  阅读:261  来源: 互联网

标签:sz ch maxlen 第十六届 int link 福州大学 程序设计 trans


H 洪尼玛的保险箱

题意:

求两个字符串的公共子串个数,且该公共子串在第一个串中以奇数位置结尾,在第二个串中以偶数位置结尾

思路:

建广义后缀自动机后根据限制条件求出每个状态的\(|endpos|\),统计答案即可

#include<cstring>
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstdlib>
#include<vector>
using namespace std;
typedef long long ll;
const int Maxn = 400010;
const int N = 2;
struct Suffix_Automata{
    int maxlen[Maxn], trans[Maxn][26], link[Maxn], Size;
    int sz[Maxn][N];
	void clr(int x){
        maxlen[x] = link[x] = 0;
        memset(trans[x], 0, sizeof(trans[x]));
        memset(sz[x], 0, sizeof(sz[x]));
    }
    void init(){
        Size = 1;
        clr(1);
    }
    int insert(int ch, int last, int id, int idx){
        if (trans[last][ch]){
            int p = last, x = trans[p][ch];
            if (maxlen[p] + 1 == maxlen[x]){
                if(id ^ idx)
                    sz[x][id] = 1; 
                return x;
            }else{
                int y = ++Size;
                clr(y);
                maxlen[y] = maxlen[p] + 1;
                for (int i = 0; i < 26; ++i)
                    trans[y][i] = trans[x][i];
                while (p && trans[p][ch] == x)
                    trans[p][ch] = y, p = link[p];
                link[y] = link[x], link[x] = y;
                if(id ^ idx)
                    sz[y][id] = 1;
                return y;
            }
        }
        int z = ++Size, p = last;
        clr(z);
        if(id ^ idx)
            sz[z][id] = 1;
        maxlen[z] = maxlen[last] + 1;
        while (p && !trans[p][ch])
            trans[p][ch] = z, p = link[p];
        if (!p) link[z] = 1;
        else{
            int x = trans[p][ch];
            if (maxlen[p] + 1 == maxlen[x]) link[z] = x;
            else{
                int y = ++Size;
                clr(y);
                maxlen[y] = maxlen[p] + 1;
                for (int i = 0; i < 26; ++i)
                    trans[y][i] = trans[x][i];
                while (p && trans[p][ch] == x)
                    trans[p][ch] = y, p = link[p];
                link[y] = link[x], link[z] = link[x] = y;
            }
        }
        return z;
    }
    int c[Maxn], a[Maxn];
    void rsort(int n){
        for(int i = 0; i <= n; ++i) c[i] = a[i] = 0;;
        for (int i = 1; i <= Size; i++) c[maxlen[i]]++;
        for (int i = 1; i <= n; i++) c[i] += c[i - 1];
        for (int i = 1; i <= Size; i++) a[c[maxlen[i]]--] = i;
        for (int i = Size; i >= 1; i--) sz[link[a[i]]][0] += sz[a[i]][0], sz[link[a[i]]][1] += sz[a[i]][1];
    }
    void solve(){
        ll ans = 0;
        for(int i = 1; i <= Size; ++i)
            ans += 1ll * sz[i][0] * sz[i][1] * (maxlen[i] - maxlen[link[i]]);
        printf("%lld\n", ans);

    }
}sam;
char s1[100010], s2[100010];
int main(){
    while(~scanf("%s%s", s1 + 1, s2 + 1)){
        int n = strlen(s1 + 1), m = strlen(s2 + 1);
        sam.init();
        int last = 1;
        for(int i = 1; i <= n; ++i) last = sam.insert(s1[i] - 'a', last, 0, i & 1);
        last = 1;
        for(int i = 1; i <= m; ++i) last = sam.insert(s2[i] - 'a', last, 1, i & 1);
        sam.rsort(max(n, m));
        sam.solve();
    }
    return 0;
}

标签:sz,ch,maxlen,第十六届,int,link,福州大学,程序设计,trans
来源: https://www.cnblogs.com/Zeronera/p/14726554.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有