zoukankan      html  css  js  c++  java
  • 【AC自动机】【状压dp】hdu2825 Wireless Password

    f(i,j,S)表示当前字符串总长度为i,dp到AC自动机第j个结点,单词集合为S时的方案数。

    要注意有点卡常数,注意代码里的注释。

    #include<cstdio>
    #include<cstring>
    #include<queue>
    using namespace std;
    queue<int>q;
    #define MOD 20090717;
    int child[111][26],fail[111],size,f[30][111][1100],tag[111];
    void Insert(char S[],int id)
    {
        int len=strlen(S);
        int now=0;
        for(int i=0;i<len;++i)
          {
            if(!child[now][S[i]-'a'])
              child[now][S[i]-'a']=size++;
            now=child[now][S[i]-'a'];
          }
        tag[now]|=(1<<id);
    }
    void build()
    {
        fail[0]=-1;
        q.push(0);
        while(!q.empty())
          {
            int U=q.front(); q.pop();
            for(int i=0;i<26;++i)
              if(child[U][i])
                {
                  int V=fail[U];
                  while(V!=-1)
                    {
                      if(child[V][i])
                        {
                          fail[child[U][i]]=child[V][i];
                          break;
                        }
                      V=fail[V];
                    }
                  if(V==-1)
                    fail[child[U][i]]=0;
                  tag[child[U][i]]|=tag[fail[child[U][i]]];
                  q.push(child[U][i]);
                }
              else if(U)
                child[U][i]=child[fail[U]][i];
          }
    }
    void Init()
    {
        memset(child,0,sizeof(child));
        memset(fail,0,sizeof(fail));
        memset(tag,0,sizeof(tag));
        size=1;
    }
    int n,m,K;
    bool check(int x)
    {
    	int res=0;
    	for(int i=0;i<m;++i)
    	  res+=((x>>i)&1);
    	return res>=K;
    }
    int main()
    {
    	//freopen("hdu2825.in","r",stdin);
    	char s[13];
    	while(1)
    	  {
    	  	scanf("%d%d%d",&n,&m,&K);
    	  	if(n==0 && m==0 && K==0)
    	  	  break;
    	  	Init();
    	  	for(int i=0;i<m;++i)
    	  	  {
    	  	  	scanf("%s",s);
    	  	  	Insert(s,i);
    	  	  }
    	  	build();
    		for(int i=0;i<=n;++i)
    	  	  for(int j=0;j<size;++j)
    	  	    for(int k=0;k<(1<<m);++k)
    	  		  f[i][j][k]=0;//用memset也许会TLE 
    	  	f[0][0][0]=1;
    	  	for(int i=0;i<n;++i)
    	  	  for(int j=0;j<size;++j)
    	  	    for(int k=0;k<(1<<m);++k)
    	  	      {
    	  	      	if(!f[i][j][k])//不加会TLE 
    	  	      	  continue;
    	  	      	for(int l=0;l<26;++l)
    	  	    	  f[i+1][child[j][l]][k|tag[child[j][l]]]=
    					(f[i+1][child[j][l]][k|tag[child[j][l]]]+f[i][j][k])%MOD;
    	  	      }
    	  		  
    		int ans=0;
    		for(int i=0;i<(1<<m);++i)
    		  if(check(i))
    		    for(int j=0;j<size;++j)
    		      ans=(ans+f[n][j][i])%MOD;
    		printf("%d
    ",ans);
    	  }
    	return 0;
    }
  • 相关阅读:
    福大软工1816 · 第五次作业
    团队编程
    结队第一次作业
    词频统计 ——Java
    Alpha 冲刺 (3/10)
    Alpha 冲刺 (2/10)
    Alpha 冲刺 (1/10)
    2018软工实践第七次作业——需求报告分析
    福大软工 · 第八次作业(课堂实战)- 项目UML设计(团队)
    2018软工实践第六次作业——团队选题报告
  • 原文地址:https://www.cnblogs.com/autsky-jadek/p/6504830.html
Copyright © 2011-2022 走看看