CF271D Good Substrings SAM
阿新 • • 發佈:2021-01-02
題意:
分析:
建出SAM,然後 \(dfs\) 將不好字元的轉移代價設定為 \(1\) ,好的字元的轉移代價設定為 \(0\) 這樣題意等價於求本質不同的長度小於等於 \(k\) 的字串個數,\(O(nk)\) 的轉移就行了
程式碼:
#include<bits/stdc++.h> using namespace std; namespace zzc { inline int read() { int x=0,f=1;char ch=getchar(); while (!isdigit(ch)){if (ch=='-') f=-1;ch=getchar();} while (isdigit(ch)){x=x*10+ch-48;ch=getchar();} return x*f; } const int maxn = 1e4+5; int n,k; int f[maxn][1505]; char ch[maxn]; bool vis[maxn],chk[26]; struct suffix_automaton { int cnt,lst; int link[maxn],trans[maxn][26],len[maxn]; suffix_automaton(){cnt=lst=1;} void insert(int x) { int cur=++cnt,tmp=lst;lst=cnt; len[cur]=len[tmp]+1; for(;tmp&&!trans[tmp][x];tmp=link[tmp]) trans[tmp][x]=cur; if(!tmp) { link[cur]=1; } else { int q=trans[tmp][x]; if(len[tmp]+1==len[q]) { link[cur]=q; } else { int clone=++cnt; len[clone]=len[tmp]+1; link[clone]=link[q]; link[cur]=link[q]=clone; for(int i=0;i<26;i++) trans[clone][i]=trans[q][i]; for(;tmp&&trans[tmp][x]==q;tmp=link[tmp]) trans[tmp][x]=clone; } } } void dfs(int u=1) { vis[u]=true; for(int i=0;i<26;i++) { int v=trans[u][i]; if(!v) continue; if(!vis[v]) dfs(v); f[u][chk[i]]++; for(int j=0;j<=k;j++) if(j-chk[i]>=0) f[u][j]+=f[v][j-chk[i]]; } } }sam; void work() { scanf("%s",ch+1);n=strlen(ch+1); for(int i=1;i<=n;i++) sam.insert(ch[i]-'a'); scanf("%s",ch); for(int i=0;i<26;i++) chk[i]=(ch[i]=='0'); k=read(); sam.dfs(); long long ans=0; for(int i=0;i<=k;i++) ans+=f[1][i]; printf("%lld\n",ans); } } int main() { zzc::work(); return 0; }