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的更多相关文章
随机推荐
- Python开发【第十八篇】:MySQL(二)
视图 视图是一个虚拟表(非真实存在),其本质是[根据SQL语句获取动态的数据集,并为其命名],用户使用时只需使用[名称]即可获取结果集,并可以将其当作表来使用. SELECT * FROM ( SEL ...
- 使用Robomongo 连接MongoDB 3.x 报 Authorization failed 解决办法(转)
最近安装了mongodb3.1.4,并启用了权限验证,在dos窗口下操作没有任何问题,为了维护方便就下载了一个客户端工具Robomongo 0.8.5,用户名.密码的等配置好点解测试,结果连接服务没有 ...
- Xcode 历史版本
概述[编辑] Xcode前身是继承自NeXT的Project Builder. The Xcode suite包含有GNU Compiler Collection自由软件(GCC.apple-darw ...
- [js/jquery]移动端手势拖动,放大,缩小预览图片
摘要 有这样的需求需要在手机端预览图片的时候,实现图片的手势拖动,放大缩小功能.最终通过touch.js这个插件实现了效果. touch.js Touch.js是移动设备上的手势识别与事件库, 由百度 ...
- logrotate关于日志轮询和分割
如果你的是源码包安装的服务,那么对于Linux服务器上的一些服务在运行当中产生的日志很重要,可以判断你的服务是否有异常等,但源码包安装的日志是没有日志的轮询或者说是切割能力的, 所以你就需要用到bas ...
- hdu3729 I'm Telling the Truth (二分图的最大匹配)
http://acm.hdu.edu.cn/showproblem.php?pid=3729 I'm Telling the Truth Time Limit: 2000/1000 MS (Java/ ...
- c# 获取系统时间
//获取日期+时间DateTime.Now.ToString(); // 2008-9-4 20:02:10DateTime.Now.ToLocalTime().ToStrin ...
- SQL--表分区
use Test --.创建数据库文件组>>alter database <数据库名> add filegroup <文件组名> ALTER DATABASE TE ...
- 关于转录组比对STAR软件使用
参考文章:http://weibo.com/p/23041883f77c940102vbkd?sudaref=passport.weibo.com 软件连接:https://github.com/al ...
- MMTx使用说明
MMTx(MetaMap Transfer)是美国国家医学图书馆建立的用于文本数据挖掘的一种工具. 下面以Medine格式数据为例介绍使用方法 1.在PubMed数据库检索相关的文献. 2.将数据结果 ...