zoukankan      html  css  js  c++  java
  • 循环移位(后缀自动机)

    题目描述:

    给定一个字符串 s 。现在问你有多少个本质不同的 s 的子串 t=tt⋯ t(m>0使得将 t 循环左移一位后变成的 t=t⋯ tt1 也是 s 的一个子串。

    题解:

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    const int N=300010;
    char s[N];
    int n,lst=1,tot=1;
    int len[N*2],ch[N*2][26],fa[N*2],pos[N*2];
    //pos表示在原串中的位置
    int sum[N][26];
    ll ans;
    void add(int c){
        int p=lst,np=lst=++tot;
        pos[np]=len[np]=len[p]+1;
        for(;p&&!ch[p][c];p=fa[p]) ch[p][c]=np;
        if(!p) fa[np]=1;
        else{
            int q=ch[p][c];
            if(len[q]==len[p]+1) fa[np]=q;
            else{
                int nq=++tot;
                memcpy(ch[nq],ch[q],sizeof(ch[q]));
                fa[nq]=fa[q];
                len[nq]=len[p]+1;
                pos[nq]=pos[q];
                fa[q]=fa[np]=nq;
                for(;p&&ch[p][c]==q;p=fa[p]) ch[p][c]=nq;
            }
        }
        return;
    }
    int main(){
        scanf("%s",s+1);
        n=strlen(s+1);
        for(int i=1;i<=n;i++)
            add(s[i]-'a');
        for(int i=1;i<=n;i++)
            for(int j=0;j<26;j++)
                sum[i][j]=sum[i-1][j]+(s[i]-'a'==j);
        for(int i=2;i<=tot;i++){
            if(ch[fa[i]][s[pos[i]-len[fa[i]]]-'a'])
                ans++;
            for(int j=0;j<26;j++)
                if(ch[i][j])
                    ans+=sum[pos[i]-len[fa[i]]-1][j]-sum[pos[i]-len[i]][j];
        }
        printf("%lld",ans);
        return 0;
    }

    好了我知道这个不好懂,所以我们再配张图:

  • 相关阅读:
    Jmeter执行流程分析
    curl获取公网IP地址
    搭建redis集群
    基于bind搭建DNS主从
    centos7设置iptables
    rabbitmq常用命令
    防火墙
    定时任务和配置中心
    Maven中pom.xml配置文件详细介绍
    Grafana+Prometheus监控
  • 原文地址:https://www.cnblogs.com/HarryPotter-fan/p/11385786.html
Copyright © 2011-2022 走看看