poj3341
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的更多相关文章
随机推荐
- Java操作Oracle
public class DBCon { // 数据库驱动对象 public static final String DRIVER = "oracle.jdbc.driver.OracleD ...
- 使用Struts 2框架实现文件下载
从服务器发送一个文件到浏览器需要以下几个步骤 把HTTP响应里的ContentType标头设置为被下载文件的内容类型.ContentType标头的作用是表明数据包里的数据是什么类型, 它由一个多媒体类 ...
- connect() failed (111: Connection refused) while connecting to upstream
配置好lamp后,在浏览器中运行程序后,出现上面的错误. 转自:http://www.xuejiehome.com/blread-1828.html I'm experiencing 502 gate ...
- Python画图笔记
matplotlib的官方网址:http://matplotlib.org/ 问题 Python Matplotlib画图,在坐标轴.标题显示这五个字符 ⊥ + - ⊺ ⨁,并且保存后也能显示 h ...
- Xshell4注册码,Xftp注册码
Xshell 是一个强大的安全终端模拟软件,商业版注册码如下: Xshell 4 注册码: 690313-111999-999313 Xftp 4 注册码:101210-450789-147200 X ...
- Unix时间戳转换怎样在Excel批量修改?
最近在操作项目的时候碰到一个Unix时间戳转换的问题."date_time":1393031347这个是什么,你知道吗?如果你对Unix时间戳了解的话一眼就看出来.但我们本着科普的 ...
- eclipse工具背景色模板-程序员保护好自己的眼睛
做为coder,要保护好自己的眼睛,eclipse 强烈推荐 Eclipse Color Theme插件,该插件包含多种当前流行的主题选择. 安装方法: 安装方法:1.先安装一个Eclipse Col ...
- Nginx的作用
负载均衡 现在几乎看不到单机奋斗的应用了吧.反向代理服务器可以根据负载均衡算法进行均匀或者自定义的转发.常见的负载均衡算法有:轮转算法(Round Robin).最少连接算法(Least Connec ...
- phpcms中常用代码总结
1.调用数据库模型 $this->db = pc_base::load_model('test_model');//从"phpcms/model/"目录下加载模型类文件 其中 ...
- HDU 1086You can Solve a Geometry Problem too(判断两条选段是否有交点)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1086 判断两条线段是否有交点,我用的是跨立实验法: 两条线段分别是A1到B1,A2到B2,很显然,如果 ...