HDU 4641 至少出现K次本质不同子串数:后缀自动机

来源:互联网 发布:软件项目评分标准 编辑:程序博客网 时间:2024/05/20 00:37

题意:先给出一个串,然后有若干操作。操作1:在结尾续上一个新字符。操作2:查询至少出现了K次的,本质不同的子串个数。


题解:SAM裸题,插入一个新的字符之后,就暴力在parent上转移++,但是也不能那么暴力,我们知道parent链上的num是单调增的,当遇到一个num>=k的点就不需要再继续走了,因为前边的肯定统计到答案里边了。


Code:

#include<bits/stdc++.h>using namespace std;const int maxn = 25e4+1000;char s[maxn];int len,k,n,m;char temp[5];struct SAM{int last,cnt,nxt[maxn*2][26],fa[maxn*2],l[maxn*2],num[maxn*2];int ans;void init(){last = cnt=1;memset(nxt[1],0,sizeof nxt[1]);fa[1]=l[1]=num[1]=0;ans=0;}int inline newnode(){cnt++;memset(nxt[cnt],0,sizeof nxt[cnt]);fa[cnt]=l[cnt]=num[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];                  num[nq] = num[q];                l[nq] = l[p]+1;                  fa[np] =fa[q] =nq;                  while (nxt[p][c]==q){                      nxt[p][c]=nq;                      p = fa[p];                  }              }          }int temp = last;while (temp){if (num[temp]>=k){break;}num[temp]++;if (num[temp]==k){ans+=l[temp]-l[fa[temp]];}temp = fa[temp];}  }}sam;int main(){while (scanf("%d%d%d",&n,&m,&k)!=EOF){scanf("%s",s);len = strlen(s);sam.init();for (int i=0;i<len;i++){sam.add(s[i]-'a');}while (m--){int flag;scanf("%d",&flag);if (flag==1){scanf("%s",temp);sam.add(temp[0]-'a');}else{printf("%d\n",sam.ans);}}}return 0;} 


阅读全文
0 0
原创粉丝点击