社区讨论
能帮忙卡发常吗
学术版参与者 3已保存回复 3
讨论操作
快速查看讨论及其快照的属性,并进行相关操作。
- 当前回复
- 3 条
- 当前快照
- 1 份
- 快照标识符
- @lo7sx4n2
- 此快照首次捕获于
- 2023/10/27 07:14 2 年前
- 此快照最后确认于
- 2023/10/27 07:14 2 年前
RT,有trie,矩阵快速幂的板子,我似乎写的有点丑了
(帮忙卡一下板子就行了)
CPP#include <bits/stdc++.h>
using namespace std;
const int N=2e3+5;
int p=1e9+7;
int n,m,l;
typedef long long ll;
string s[201];
int tree[N][26],cnt;
bool ex[N];
int d[1001][1001];
struct mrt {
ll a[201][201];
int sz;
mrt operator *(const mrt &x)const{
mrt ret;
for(int i=0;i<=sz;++i)
for(int j=0;j<=sz;++j) ret.a[i][j]=0;
ret.sz=sz;
for(int i=0;i<=sz;++i)
for(int j=0;j<=sz;++j)
for(int k=0;k<=sz;++k)
ret.a[i][j]=(ret.a[i][j]+a[k][j]*x.a[i][k]%p)%p;
return ret;
}
};
mrt A;
inline void insert(string s) {
int t=0;
for(int i=0; i<s.size(); ++i) {
if(tree[t][s[i]-'a']==0) tree[t][s[i]-'a']=++cnt;
t=tree[t][s[i]-'a'];
}
ex[t]=1;
}
int fail[N];
inline void build() {
queue<int> qu;
for(int i=0;i<26;++i) if(tree[0][i]) qu.push(tree[0][i]);
while(!qu.empty())
{
int t=qu.front();qu.pop();
ex[t]|=ex[fail[t]];
for(int i=0;i<26;++i)
{
if(tree[t][i])
{
fail[tree[t][i]]=tree[fail[t]][i];
qu.push(tree[t][i]);
}
else
{
tree[t][i]=tree[fail[t]][i];
}
}
}
}
inline int find(int t,string s) {
for(int i=0; i<s.size(); ++i)
if(ex[t]) return t;
else t=tree[t][s[i]-'a'];
return t;
}
inline mrt ksm(int x)
{
mrt bas=A,ret;ret.sz=A.sz;
for(int i=0;i<ret.sz;++i)
for(int j=0;j<ret.sz;++j) ret.a[i][j]=0;
for(int i=0;i<=ret.sz;++i) ret.a[i][i]=1;
while(x)
{
if(x&1) ret=ret*bas;
x>>=1;
bas=bas*bas;
}
return ret;
}
int main() {
// freopen("in.in","r",stdin);
ios::sync_with_stdio(false);
cin>>n>>m>>l;
for(int i=1; i<=n; ++i) {
cin>>s[i];
}
for(int i=1; i<=m; ++i) {
string s;
cin>>s;
insert(s);
}
build();
if(l<=100) {
d[0][0]=1;
for(int i=0; i<=l; ++i) {
for(int j=0; j<=cnt; ++j) {
if(d[i][j]==0) continue;
for(int k=1; k<=n; ++k) {
if(i+s[k].size()>l) continue;
int to=find(j,s[k]);
if(ex[to]) continue;
d[i+s[k].size()][to]=(d[i+s[k].size()][to]+d[i][j])%p;
}
}
}
int ans=0;
for(int i=0; i<=cnt; ++i) ans=(ans+d[l][i])%p;
cout<<ans<<endl;
} else {
A.sz=cnt*2+1;
for(int i=0; i<=cnt; ++i) A.a[i][i+cnt+1]=1;
for(int i=0; i<=cnt; ++i) {
if(ex[i]) continue;
for(int k=1; k<=n; ++k) {
if(s[k].size()==1) {
if(ex[tree[i][s[k][0]-'a']]) continue;
A.a[tree[i][s[k][0]-'a']+1+cnt][i+cnt+1]++;
}
else {
int p=find(i,s[k]);
if(ex[p]) continue;
A.a[p+1+cnt][i]++;
}
}
}
mrt B;
B.sz=A.sz;
B.a[cnt+1][0]=1;
B=B*ksm(l);
ll ans=0;
for(int i=0;i<=cnt;++i) ans=(ans+B.a[cnt+i+1][0])%p;
cout<<ans<<endl;
}
return 0;
}
回复
共 3 条回复,欢迎继续交流。
正在加载回复...