洛谷P4052 [JSOI2007]文本生成器 AC自動機+dp
阿新 • • 發佈:2019-04-03
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> usingView Codenamespace 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; }
洛谷P4052 [JSOI2007]文本生成器 AC自動機+dp