题意:
分析:
建出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
",ans);
}
}
int main()
{
zzc::work();
return 0;
}