1. 程式人生 > >洛谷P4052 [JSOI2007]文本生成器 AC自動機+dp

洛谷P4052 [JSOI2007]文本生成器 AC自動機+dp

display gis 那種 pre ide emp while sed printf

正解:AC自動機+dp

解題報告:

傳送門!

感覺AC自動機套dp的題還挺套路的,,,

一般就先跑遍AC自動機,然後就用dp

dp的狀態一般都是f[i][j]:有i個字符,是ac自動機上的第j個節點,然後有的題目可能還要加一維用來滿足一些額外要求之類的

然後聽說矩陣優化dp挺常見的,,,但我還沒做過這種題QAQ

然後這題就直接很套路啊,,,直接上面那種套路一點修改都沒有,,,

就顯然答案是所有狀態-非法狀態

所有狀態就26m

非法狀態就上面那個套路算下

然後就做完了呢,,,

放下代碼趴QAQ

技術分享圖片
#include<bits/stdc++.h>
using
namespace std; #define il inline #define gc getchar() #define ll long long #define ri register int #define rb register bool #define rc register char #define rp(i,x,y) for(ri i=x;i<=y;++i) #define my(i,x,y) for(ri i=x;i>=y;--i) const int N=1000+10,mod=10007; int n,m,nod_cnt,as,f[N][N*10];
struct nod{int to[30],fail;bool flg;}tr[N*10]; char str[N]; queue<int>Q; il int read() { rc ch=gc;ri x=0;rb y=1; while(ch!=- && (ch>9 || ch<0))ch=gc; if(ch==-)ch=gc,y=0; while(ch>=0 && ch<=9)x=(x<<1)+(x<<3)+(ch^0),ch=gc;
return y?x:x; } il void insert(char *s) { ri lth=strlen(s+1),nw=0; rp(i,1,lth) { if(!tr[nw].to[s[i]-A+1])tr[nw].to[s[i]-A+1]=++nod_cnt; nw=tr[nw].to[s[i]-A+1]; } tr[nw].flg=1; } il void bfs() { rp(i,1,26)if(tr[0].to[i])Q.push(tr[0].to[i]); while(!Q.empty()) { ri nw=Q.front();Q.pop();tr[nw].flg|=tr[tr[nw].fail].flg; rp(i,1,26) if(tr[nw].to[i])Q.push(tr[nw].to[i]),tr[tr[nw].to[i]].fail=tr[tr[nw].fail].to[i]; else tr[nw].to[i]=tr[tr[nw].fail].to[i]; } } il int power(ri x,ri y){ri ret=1;while(y){if(y&1)ret=ret*x%mod;x=x*x%mod;y>>=1;}return ret;} int main() { n=read();m=read();rp(i,1,n){scanf("%s",str+1);insert(str);}bfs(); as=power(26,m);f[0][0]=1; rp(i,0,m-1) rp(j,0,nod_cnt) if(!tr[j].flg) rp(k,1,26) if(!tr[tr[j].to[k]].flg)f[i+1][tr[j].to[k]]=(f[i+1][tr[j].to[k]]+f[i][j])%mod; rp(i,0,nod_cnt)as=(as+mod-f[m][i])%mod; printf("%d\n",as); return 0; }
View Code

洛谷P4052 [JSOI2007]文本生成器 AC自動機+dp