题意:
分析:
- 暴力
(O(n^2)) 的 DP ,(f[i][j]=f[i-1][j-1]+f[i][j-1]*25)
- 正解
我们发现 DP 方程与原串的形态无关,然后观察(题解) 式子,发现它可以通过组合数优化
(f_{i,j}=C_{i-1}^{j-1} imes 25^{j-i}+C_i^{j-1} imes 26)
这个递推式的含义就是:
-
前 (j-1) 位匹配上了原来 (i-1) 个,为了避免算重,每一位的取值不能等于下一个要匹配的数,所以取值种类有 25 种,空余位置有 (j-i) 个
-
前 (j-1) 位匹配完了,之后随意取
然后我们对于长度对应的答案进行记忆化,由于不同长度的串的种类数最多只有 (sqrt{10^5}) 种,所以复杂度是 (O(nsqrt{n}))
代码:
#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 = 1e5+5;
const int mod = 1e9+7;
char ch[maxn];
vector<int> f[maxn];
int fac[maxn],inv[maxn],pw[maxn];
bool vis[maxn];
int n,len;
void init()
{
fac[0]=fac[1]=inv[0]=inv[1]=pw[0]=1;
pw[1]=25;
for(int i=2;i<=100000;i++) fac[i]=1ll*fac[i-1]*i%mod,inv[i]=1ll*inv[mod%i]*(mod-mod/i)%mod,pw[i]=1ll*pw[i-1]*25%mod;
for(int i=2;i<=100000;i++) inv[i]=1ll*inv[i-1]*inv[i]%mod;
}
long long C(long long n,long long m)
{
return 1ll*fac[n]*inv[n-m]%mod*inv[m]%mod;
}
void solve()
{
if(!vis[len])
{
vis[len]=true;
for(int i=0;i<len;i++) f[len].push_back(0);
for(int i=len;i<=100000;i++) f[len].push_back((1ll*C(i-1,len-1)*pw[i-len]%mod+1ll*f[len][i-1]*26%mod)%mod);
}
printf("%d
",f[len][read()]%mod);
}
void work()
{
init();
n=read();
scanf("%s",ch);len=strlen(ch);
for(int i=1;i<=n;i++)
{
if(read()==1)
{
scanf("%s",ch);
len=strlen(ch);
}
else solve();
}
}
}
int main()
{
zzc::work();
return 0;
}