转自:http://blog.youkuaiyun.com/ascii991/article/details/7462427
【题意】
给定N个字符集合和P个禁用的字符串,求长度为M的合法字符串个数。
【题解】
显然是AC自动机上的DP。
令dp[i][j]表示长度为i,状态为j的字符串个数。
按自动机的图转移即可,但要注意细节。
贡献几组数据。
50 50 10
qwertyuiop[]\asdfghjkl;'zxcvbnm,./ QWERTYUIOP{}|AS
aegaegu
etoijqt
tquqi
witowwt
zxcjnc
oeit
potieq
iojge
nvoq
piqper
ans=8881647922834867244791415981705771412427494861672253136057167374729235842468240763290
1 1 1
a
a
ans=0
5 10 3
abcde
abc
bc
c
ans=1048576
- #include
- #include
- using namespace std;
- const int maxn=800,maxm=55,base=100000000,kind=55;
- struct node
- {
- int sum,id;
- node* ch[kind];
- node* fail;
- }a[maxn];
- struct num
- {
- int g[20];
- int len;
- num()
- {
- memset(g,0,sizeof(g));
- len=1;
- }
- }dp[maxm][maxn];
- char s[maxm];
- int dx[400];
- int n,m,p,tot=0;
- node* getroot()
- {
- tot++;
- int i;
- for (i=0;i
- a[tot].ch[i]=0;
- a[tot].fail=0;
- a[tot].id=tot;
- a[tot].sum=0;
- return &a[tot];
- }
- node* root=getroot();
- node* getnode()
- {
- tot++;
- int i;
- for (i=0;i
- a[tot].ch[i]=0;
- a[tot].fail=root;
- a[tot].id=tot;
- a[tot].sum=0;
- return &a[tot];
- }
- void ins(char* s)
- {
- int i,k,len=strlen(s);
- node* now=root;
- for (i=0;i
- {
- k=dx[s[i]+128];
- if (now->ch[k]==0)
- now->ch[k]=getnode();
- now=now->ch[k];
- }
- now->sum++;
- }
- void init()
- {
- int i;
- char st[maxm];
- scanf("%d%d%d\n",&n,&m,&p);
- gets(s);
- for (i=0;i
- dx[s[i]+128]=i;
- for (i=1;i<=p;i++)
- {
- scanf("%s",st);
- ins(st);
- }
- }
- queue q;
- void build()
- {
- int i,k;
- node* now,*ff;
- q.push(root);
- while (!q.empty())
- {
- now=q.front();
- q.pop();
- for (i=0;i
- if (now->ch[i]!=0)
- {
- q.push(now->ch[i]);
- for (ff=now->fail;ff!=0;ff=ff->fail)
- if (ff->ch[i]!=0)
- {
- now->ch[i]->fail=ff->ch[i];
- if (ff->ch[i]->sum==1) now->ch[i]->sum=1;
- break;
- }
- }
- }
- }
- num operator +(num a,num b)
- {
- num c=num();
- int i,t,k=0,len=max(a.len,b.len);
- for (i=1;i<=len;i++)
- {
- t=a.g[i]+b.g[i]+k;
- k=t/base;
- c.g[i]=t�se;
- }
- while (k)
- {
- c.g[++len]=k�se;
- k/=base;
- }
- c.len=len;
- return c;
- }
- void DP()
- {
- int i,j,k;
- dp[0][1].g[1]=1;
- for (i=0;i
- for (j=1;j<=tot;j++)
- {
- node* now=&a[j];
- for (k=0;k
- if (now->ch[k]!=0)
- {
- int ct=now->ch[k]->id;
- if (now->ch[k]->sum==0) dp[i+1][ct]=dp[i+1][ct]+dp[i][j];
- }
- else
- {
- node* tmp=now->fail;
- for (;tmp!=0;tmp=tmp->fail)
- if (tmp->ch[k]!=0)
- {
- tmp=tmp->ch[k];
- break;
- }
- if (tmp==0) tmp=root;
- int ct=tmp->id;
- if (tmp->sum==0) dp[i+1][ct]=dp[i+1][ct]+dp[i][j];
- }
- }
- }
- void print()
- {
- int i,j;
- num ans=num();
- for (i=1;i<=tot;i++)
- ans=ans+dp[m][i];
- j=ans.len;
- printf("%d",ans.g[j]);
- for (i=j-1;i>=1;i--)
- {
- if (ans.g[i]"0");
- if (ans.g[i]"0");
- if (ans.g[i]"0");
- if (ans.g[i]"0");
- if (ans.g[i]"0");
- if (ans.g[i]"0");
- if (ans.g[i]"0");
- printf("%d",ans.g[i]);
- }
- printf("\n");
- }
- int main()
- {
- freopen("pin.txt","r",stdin);
- freopen("pou.txt","w",stdout);
- init();
- build();
- DP();
- print();
- return 0;
- }