社区讨论

能帮忙卡发常吗

学术版参与者 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 条回复,欢迎继续交流。

正在加载回复...