自动机上状压dp,把单词是否存在压成二进制位
注意这里面某些单词会包含其他单词,所以某些自动机上有些状态点对应多个二进制位
方案只要再顺着有方案的状态搜一遍即可

  1 var trie,go:array[0..110,'a'..'z'] of longint;
  2     f,q,v:array[0..110] of longint;
  3     ans:array[0..50] of string;
  4     dp:array[0..25,0..100,0..1023] of int64;
  5     t,k,i,j,n,m,l:longint;
  6     c:char;
  7     s:string;
  8 
  9 function calc(n:longint):int64;
 10   var i:longint;
 11   begin
 12     calc:=1;
 13     for i:=1 to n do
 14       calc:=calc*26;
 15   end;
 16 
 17 procedure ac;
 18   var h,r,x,y,j,i:longint;
 19       c:char;
 20   begin
 21     h:=1;
 22     r:=0;
 23     for c:='a' to 'z' do
 24       if trie[0,c]>0 then
 25       begin
 26         inc(r);
 27         q[r]:=trie[0,c];
 28       end;
 29 
 30     while h<=r do
 31     begin
 32       x:=q[h];
 33       for c:='a' to 'z' do
 34         if trie[x,c]>0 then
 35         begin
 36           y:=trie[x,c];
 37           inc(r);
 38           q[r]:=y;
 39           j:=f[x];
 40           while (j>0) and (trie[j,c]=0) do j:=f[j];
 41           f[y]:=trie[j,c];
 42           v[y]:=v[y] or v[trie[j,c]];
 43         end;
 44       inc(h);
 45     end;
 46   end;
 47 
 48 function dfs(i,p,q:longint):int64;
 49   var c:char;
 50   begin
 51     if i=m then
 52     begin
 53       if q=1 shl n-1 then dp[i,p,q]:=1
 54       else dp[i,p,q]:=0;
 55     end;
 56     if dp[i,p,q]<>-1 then exit(dp[i,p,q]);
 57     if (q=1 shl n-1) and (m-i<2) then exit(calc(m-i));
 58     dp[i,p,q]:=0;
 59     for c:='a' to 'z' do
 60       dp[i,p,q]:=dp[i,p,q]+dfs(i+1,go[p,c],q or v[go[p,c]]);
 61     exit(dp[i,p,q]);
 62   end;
 63 
 64 procedure get(i,p,q:longint);
 65   var c:char;
 66       j:longint;
 67   begin
 68     if i=m then
 69     begin
 70       inc(t);
 71       ans[t]:=s;
 72     end
 73     else begin
 74       for c:='a' to 'z' do
 75         if dp[i+1,go[p,c],q or v[go[p,c]]]>0 then
 76         begin
 77           s[i+1]:=c;
 78           get(i+1,go[p,c],q or v[go[p,c]]);
 79         end;
 80     end;
 81   end;
 82 
 83 begin
 84   readln(m,n);
 85   for i:=1 to n do
 86   begin
 87     j:=0;
 88     readln(s);
 89     l:=length(s);
 90     for k:=1 to l do
 91     begin
 92       if trie[j,s[k]]=0 then
 93       begin
 94         inc(t);
 95         trie[j,s[k]]:=t;
 96       end;
 97       j:=trie[j,s[k]];
 98     end;
 99     v[j]:=1 shl (i-1);
100   end;
101   ac;
102   for i:=0 to t do
103     for c:='a' to 'z' do
104     begin
105       j:=i;
106       while (j>0) and (trie[j,c]=0) do j:=f[j];
107       go[i,c]:=trie[j,c];
108     end;
109 
110   fillchar(dp,sizeof(dp),255);
111   writeln(dfs(0,0,0));
112   if dp[0,0,0]<=42 then
113   begin
114     t:=0;
115     s:='';
116     for i:=1 to m do
117       s:=s+' ';
118     get(0,0,0);
119     for i:=1 to t do
120       writeln(ans[i]);
121   end;
122 end.
View Code

 

posted on 2015-02-25 18:50  acphile  阅读(199)  评论(0编辑  收藏  举报