循环移位(后缀自动机)
Posted harrypotter-fan
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了循环移位(后缀自动机)相关的知识,希望对你有一定的参考价值。
题目描述:
给定一个字符串 s 。现在问你有多少个本质不同的 s 的子串 t=t1 t2 ? tm (m>0) 使得将 t 循环左移一位后变成的 t′=t2 ? tm t1 也是 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;
好了我知道这个不好懂,所以我们再配张图:
以上是关于循环移位(后缀自动机)的主要内容,如果未能解决你的问题,请参考以下文章
hihocoder #1465 : 后缀自动机五·重复旋律8
hihocoder 后缀自动机五·重复旋律8 求循环同构串出现的次数