https://www.luogu.org/problemnew/show/P4052
https://ac.nowcoder.com/acm/problem/20155
中文题,相信大家都读得懂;
首先要求出现过的串的总数,就用总数,减去,没有出现过的,既然是几个串,那就是AC自动机,加矩阵快速幂,但不过这道题由于文本比较长所以就只有用dp刚刚开始想着用类似的数位dp的办法做,只能过一半的样列,后来暴力写,也只能过一半,最后发现fail没有更新下去。改了后,前面的类似数位dp 的还是没有过,后面的倒是过了,可能想错了吧。
dp[m][i]表示取了m位,第m位i的方法。
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int mod=10007;
const int N=6000+10;
struct Aho_Trie
{
int nxt[N][26],fail[N],endd[N];
int l,root;
int newnode()
{
endd[l]=fail[l]=0;
memset(nxt[l],0,sizeof(nxt[l]));
return l++;
}
void init()
{
l=0;
root=newnode();
}
void Insert(char *s)
{
int len=strlen(s),u=root;
for(int i=0;i<len;i++)
{
int x=s[i]-'A';
if(nxt[u][x]==0) nxt[u][x]=newnode();
u=nxt[u][x];
}
endd[u]=1;
}
void build()
{
queue<int>qu;
for(int i=0;i<26;i++)
if(nxt[root][i]!=0) qu.push(nxt[root][i]);
while(!qu.empty())
{
int u=qu.front();qu.pop();
endd[u]+=endd[fail[u]];
for(int i=0;i<26;i++)
{
if(nxt[u][i]) fail[nxt[u][i]]=nxt[fail[u]][i],qu.push(nxt[u][i]);
else nxt[u][i]=nxt[fail[u]][i];
}
}
}
}ac;
int n,m,dp[110][N];
char tmp[110];
int quick(int a,int n)
{
int ans=1;
while(n)
{
if(n&1)
ans=ans*a%mod;
a=a*a%mod;
n>>=1;
}
return ans;
}
int main()
{
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
cin>>n>>m;
ac.init();
for(int i=1;i<=n;i++)
{
cin>>tmp;
ac.Insert(tmp);
}
ac.build();
int cnt=ac.l-1;
///cout<<cnt<<endl;
memset(dp,0,sizeof(dp));
dp[0][0]=1;
for(int i=0;i<m;i++)
{
for(int j=0;j<=cnt;j++)
{
for(int k=0;k<26;k++)
{
if(!ac.endd[ac.nxt[j][k]])
dp[i+1][ac.nxt[j][k]]=(dp[i+1][ac.nxt[j][k]]+dp[i][j])%mod;
}
}
}
int ans=quick(26,m);
for(int i=0;i<=cnt;i++)
{
ans=(ans-dp[m][i]+mod)%mod;
///cout<<dp[m][i]<<endl;
}
cout<<ans<<endl;
return 0;
}