AC自动机,用40^4 * 50 * 10的空间进行dp。

最大的难点在于hash。

hash一个数列f,数列中的每一位都有一个上限g,即f[i]<=g[i]。

那么可以将该数列hash为这样一个整数,这个整数的每一个位的进制都不同,第i位的进制是g[i] + 1,即第i位满g[i]+1则可进位。(当然由于g[i]是该位的上限,所以永远不可能进位)

用p[i]表示(g[0]+1)*(g[1]+1)*...*(g[i - 1]+1)。那么最终f被hash的结果是p[0]*f[0]+p[1]*f[1]+...。

#include <cstdio>
#include <algorithm>
#include <queue>
#include <map>
#include <cstring>
using namespace std; #define D(x) const int MAX_LEN = ;
const int MAX_N = ;
const int MAX_NODE_NUM = * MAX_N;
const int MAX_CHILD_NUM = ; //1.init() 2.insert() 3.build() 4.query()
struct Trie
{
int next[MAX_NODE_NUM][MAX_CHILD_NUM];
int fail[MAX_NODE_NUM];
int count[MAX_NODE_NUM];
int node_cnt;
bool vis[MAX_NODE_NUM]; //set it to false
int root; void init()
{
node_cnt = ;
root = newnode();
memset(vis, , sizeof(vis));
} int newnode()
{
for (int i = ; i < MAX_CHILD_NUM; i++)
next[node_cnt][i] = -;
count[node_cnt++] = ;
return node_cnt - ;
} int get_id(char a)
{
if (a == 'A')
return ;
if (a == 'C')
return ;
if (a == 'T')
return ;
return ;
} void insert(char buf[])
{
int now = root;
for (int i = ; buf[i]; i++)
{
int id = get_id(buf[i]);
if (next[now][id] == -)
next[now][id] = newnode();
now = next[now][id];
}
count[now]++;
} void build()
{
queue<int>Q;
fail[root] = root;
for (int i = ; i < MAX_CHILD_NUM; i++)
if (next[root][i] == -)
next[root][i] = root;
else
{
fail[next[root][i]] = root;
Q.push(next[root][i]);
}
while (!Q.empty())
{
int now = Q.front();
Q.pop();
for (int i = ; i < MAX_CHILD_NUM; i++)
if (next[now][i] == -)
next[now][i] = next[fail[now]][i];
else
{
fail[next[now][i]]=next[fail[now]][i];
count[next[now][i]] += count[fail[next[now][i]]];
Q.push(next[now][i]);
}
}
} int query(char buf[])
{
int now = root;
int res = ; memset(vis, , sizeof(vis));
for (int i = ; buf[i]; i++)
{
now = next[now][get_id(buf[i])];
int temp = now;
while (temp != root && !vis[temp])
{
res += count[temp];
// optimization: prevent from searching this fail chain again.
//also prevent matching again.
vis[temp] = true;
temp = fail[temp];
}
}
return res;
} void debug()
{
for(int i = ;i < node_cnt;i++)
{
printf("id = %3d,fail = %3d,end = %3d,chi = [",i,fail[i],count[i]);
for(int j = ;j < MAX_CHILD_NUM;j++)
printf("%2d",next[i][j]);
printf("]\n");
}
}
}ac; char st[MAX_LEN];
int n;
int num[];
int num2[];
int dp[][]; int myhash(int f[])
{
int ret = ;
for (int i = ; i < ; i++)
{
ret += f[i] * num[i];
}
return ret;
} int work()
{
int temp[] = {};
for (int i = ; st[i]; i++)
{
temp[ac.get_id(st[i])]++;
}
num[] = ;
for (int i = ; i >= ; i--)
{
num[i] = (temp[i + ] + ) * num[i + ];
}
memset(dp, -, sizeof(dp));
int f[];
int g[];
int ret = ;
for (f[] = ; f[] <= temp[]; f[]++)
for (f[] = ; f[] <= temp[]; f[]++)
for (f[] = ; f[] <= temp[]; f[]++)
for (f[] = ; f[] <= temp[]; f[]++)
{
for (int u = ; u < ac.node_cnt; u++)
{
int h = myhash(f);
for (int j = ; j < ; j++)
{
g[j] = f[j];
}
int temp2 = ;
for (int j = ; j < ; j++)
{
g[j]--;
int h2 = myhash(g);
int v = ac.next[u][j];
if (g[j] >= )
{
temp2 = max(temp2, dp[h2][v]);
D(printf("\t\t\t%d %d %d %d %d %d %d\n", g[], g[], g[], g[], v, temp2, h2));
}
g[j]++;
}
dp[h][u] = temp2 + ac.count[u];
ret = max(ret, dp[h][u]);
D(printf("%d %d %d %d %d %d %d\n", f[], f[], f[], f[], u, dp[h][u], h));
}
}
return dp[myhash(temp)][ac.root];
} int main()
{
int t = ;
while (scanf("%d", &n), n)
{
ac.init();
for (int i = ; i < n; i++)
{
scanf("%s", st);
ac.insert(st);
}
ac.build();
scanf("%s", st);
printf("Case %d: %d\n", ++t, work());
}
return ;
}

poj3341的更多相关文章

随机推荐

  1. 图书管理系统——APP平台开发

    http://www.w3school.com.cn/php/ 初步计划采用PHP 开发网站. 一定要独立建立一套图书管理系统, 尤其唯一性质的概念,整合,甚至中英文图书概念的而整合.一本书一个页. ...

  2. abrtd是什么进程

    abrtd 是一个守护进程监控的应用程序崩溃.当发生崩溃时,它将收集的崩溃(核心文件的命令行, etc .)application ,并采取措施根据类型崩溃并根据 abrt.conf config 文 ...

  3. unzip 命令使用

    http://blog.sina.com.cn/s/blog_6c9d65a10100nzqf.html unzip命令:解压缩文件 他是解压zip压缩的文件,和zip互逆的一对工具.   命令: u ...

  4. Memcached存储命令 - add

    Memcached add 命令用于将 value(数据值) 存储在指定的 key(键) 中. 如果 add 的 key 已经存在,则不会更新数据,之前的值将仍然保持相同,并且您将获得响应 NOT_S ...

  5. sql字段中逗号分隔字符串的判断

    例如,数据表t1中有一个字段PlayTheme存放的数值类似如下: 第一行:1,2,12 第二行:22,222,2222 第三行:1,2 第四行:2,12 第五行:2 如果你想取出PlayTheme字 ...

  6. 基于iSCSI的SQL Server 2012群集测试(三)--SQL Server 2012群集安装总结

    5.SQL Server 2012群集安装总结 5.1 群集与非群集的安装区别总结 SQL Server虚拟名称: 非群集环境下,本地服务器的名称就是SQL Server服务器名称:但在群集环境下,由 ...

  7. 重温javascript事件机制

    以前用过一段时间的jquery感觉太方便,太强大了,各种动画效果,dom事件.创建节点.遍历.控件及UI库,应有尽有:开发文档也很多,网上讨论的问题更是甚多,种种迹象表明jquery是一个出色的jav ...

  8. Python命令 (if __name__=="__main__":)

    1. 语法 1.以#号开头的语句是注释 2.请务必注意,Python程序是大小写敏感的,如果写错了大小写,程序会报错. 3.按照约定俗成的管理,应该始终坚持使用4个空格的缩进. 4.当语句以冒号:结尾 ...

  9. iOS开发——源代码管理——SVN

    一.源代码管理(svn)简介 01. 源代码管理工具概述 ======================================================================= ...

  10. JQuery的Ajax跨域请求的解决方案

    客户端调用代码示例: var myurl = "http://js.yingdoo.com/embed/CAPTCHA.ashx?m=" + phone_val + "& ...