HDU 4622 本质不同的子串个数:后缀自动机

来源:互联网 发布:淘宝特卖女装清仓棉袄 编辑:程序博客网 时间:2024/06/05 08:33

题意:给出一个串,每次求一个子串[ l , r ]。问这个串中,本质不同的子串个数,多组询问,数据小。


题解:记住SAM是ON的。所以直接对每个[ l , r ]建SAM,然后建完就出答案。时间足够用。模板题为什么要写博客呢。。。。因为复用自动机的话。。要清空呀。。。。


Code:

#include<bits/stdc++.h>using namespace std;const int maxn = 2e3+100;char s[maxn];int len;int T;struct SAM{int last,cnt,nxt[maxn*2][26],fa[maxn*2],l[maxn*2];int 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];}}}//cout<<fa[last]<<endl;ans+=l[last]-l[fa[last]];}void query(){int l,r;scanf("%d%d",&l,&r);init();for (int i=l;i<=r;i++){//cout<<s[i]<<" ";add(s[i]-'a');}printf("%d\n",ans);}}sam;int main(){scanf("%d",&T);while (T--){scanf("%s",s+1);int Q;scanf("%d",&Q);while (Q--){sam.query();}}return 0;} 


阅读全文
0 0