标签:理解 ide \n mes void space const 技术 for
小Hi平时的一大兴趣爱好就是演奏钢琴。我们知道一个音乐旋律被表示为一段数构成的数列。
现在小Hi想知道一部作品中出现了多少不同的旋律?
共一行,包含一个由小写字母构成的字符串。字符串长度不超过 1000000。
一行一个整数,表示答案。
题解:
题目意思就是让你求有多少种不同的子串。
后缀自动机的板题。理解后缀自动机的longest[]数组,对于每一个状态s,它的等价类集合中的子串数量即为 l[s]-l[fa[s]];然后答案就是把每一个状态的的数量累加;
(原因就是任意两个等价类交集为空)
参考代码:
#include<bits/stdc++.h> using namespace std; const int maxn=1e6+10; char s[maxn]; int len; int T; struct SAM{ int last,cnt,nxt[maxn*2][26],fa[maxn*2],l[maxn*2]; long long ans; void init() { last = cnt=1; memset(nxt[1],0,sizeof nxt[1]); fa[1]=0;ans=0;l[1]=0; } int inline newnode() { ++cnt; memset(nxt[cnt],0,sizeof nxt[cnt]); fa[cnt]=l[cnt]=0; return cnt; } void add(int c) { int p=last; int np=newnode(); last=np; l[np]=l[p]+1; while(p&&!nxt[p][c]) { nxt[p][c]=np; p = fa[p]; } if(!p) fa[np]=1; else { int q = nxt[p][c]; if(l[q]==l[p]+1) fa[np] = q; else { int nq = newnode(); memcpy(nxt[nq],nxt[q],sizeof nxt[q]); fa[nq] = fa[q]; l[nq] = l[p]+1; fa[np]=fa[q]=nq; while (nxt[p][c]==q) { nxt[p][c]=nq; p=fa[p]; } } } ans+=(l[last]-l[fa[last]])*1ll; } void query() { int l=1,r=strlen(s+1); //scanf("%d%d",&l,&r); init(); for(int i=l;i<=r;i++) add(s[i]-‘a‘); printf("%lld\n",ans); } }sam; int main() { scanf("%s",s+1); sam.query(); return 0; }
标签:理解 ide \n mes void space const 技术 for
原文地址:https://www.cnblogs.com/songorz/p/10805025.html