标签:ati front 转移 return class printf pre problem pop
对于所有串构建AC自动机,将AC自动机上的位置作为状态,暴力矩阵转移即可
int n,m;
int a[N];
char s[N];
int val[N];
const int SIZE=101;
int trie[SIZE][4];
int End[SIZE];
int fail[SIZE],cnt;
int ch[N];
int Insert(char *s){
int p=0;
int l=0;
while(s[l]!=‘\0‘) l++;
rep(i,0,l-1) {
int x=ch[(int)s[i]];
if(!trie[p][x]) trie[p][x]=++cnt;
p=trie[p][x];
}
return p;
}
void Build() {
static queue <int> que;
rep(i,0,3) if(trie[0][i]) que.push(trie[0][i]);
while(!que.empty()) {
int u=que.front(); que.pop();
End[u]|=End[fail[u]];
rep(i,0,3) {
int &v=trie[u][i];
if(v) {
que.push(v);
fail[v]=trie[fail[u]][i];
} else v=trie[fail[u]][i];
}
}
}
struct Mat{
int a[SIZE][SIZE];
void init(){ memset(a,0,sizeof a); }
void Get1(){ rep(i,0,cnt) a[i][i]=1; }
Mat operator * (const Mat x) const{
Mat res; res.init();
rep(i,0,cnt) rep(j,0,cnt) rep(o,0,cnt) res.a[i][o]=(res.a[i][o]+1ll*a[i][j]*x.a[j][o])%P;
return res;
}
}x,res;
int f[1][SIZE],ans[1][SIZE];
int main(){
ch[(int)‘A‘]=0,ch[(int)‘T‘]=1,ch[(int)‘C‘]=2,ch[(int)‘G‘]=3;
m=rd(),n=rd();
rep(i,1,m) {
scanf("%s",s);
End[Insert(s)]=1;
}
Build();
f[0][0]=1;
rep(i,0,cnt) if(!End[i]) {
rep(j,0,3) {
int nxt=trie[i][j];
if(End[nxt]) continue;
x.a[i][nxt]++;
}
}
res.Get1();
while(n) {
if(n&1) res=res*x;
x=x*x;
n>>=1;
}
rep(i,0,0) rep(j,0,cnt) rep(o,0,cnt) ans[i][o]=(ans[i][o]+1ll*f[i][j]*res.a[j][o])%P;
int Ans=0;
rep(i,0,cnt) (Ans+=ans[0][i])%=P;
printf("%d\n",Ans);
}
标签:ati front 转移 return class printf pre problem pop
原文地址:https://www.cnblogs.com/chasedeath/p/12931289.html