• 【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;
    }
  • 相关阅读:
    004: 基本数据类型-List
    003: 基本类型-字符串类型
    002: 基本类型-数值型(int, float)
    001: Hello World
    Python中的单例模式的几种实现方式的及优化
    django之admin组件
    权限管理---设计分析以及具体细节
    基于Form组件实现的增删改和基于ModelForm实现的增删改
    Python常见问题系列
    django的render的说明
  • 原文地址:https://www.cnblogs.com/autsky-jadek/p/6504830.html
Copyright © 2020-2023  润新知