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的更多相关文章
随机推荐
- 未能正确加载“Microsoft.VisualStudio.Editor.Implementation.EditorPackage”包
解决方案: 关掉VS2012... "Microsoft Visual Studio 2012"->"Visual Studio Tools"->& ...
- js调用ios的方法
摘要 在做h5应用的时,有时有些功能js并不能实现的特别完美.比如下载进度条或上传文件进度等.如果能调用ios或者android的方法,实现进度,以及文件上传或者下载列表更好一些.如果使用第三方的js ...
- PPTP(Point to Point Tunneling Protocol),即点对点隧道协议。
PPTP PPTP(Point to Point Tunneling Protocol),即点对点隧道协议.该协议是在PPP协议的基础上开发的一种新的增强型安全协议,支持多协议虚拟专用网(VPN),可 ...
- scp命令的用法详解
这篇文章主要是参考了http://blog.csdn.net/jiangkai_nju/article/details/7338177这个博客,要看详细的内容可以参考这个博客进行学习研究,但是我觉得在 ...
- CF453B Little Pony and Harmony Chest (状压DP)
CF453B CF454D Codeforces Round #259 (Div. 2) D Codeforces Round #259 (Div. 1) B D. Little Pony and H ...
- MFC中文件的查找、创建、打开、读写等
http://blog.csdn.net/whatforever/article/details/6316416
- 【C语言入门教程】4.2 二维数组
C 语言允许使用多维数组,即使用多组小标的数组,二维数组是最常用的多维数组.多维数组在内存中存放数据的顺序与一维数组相同,使用连续的存储单元. 4.2.1 二维数组的一般形式 二维数组的一般声明形式为 ...
- C#利用Web Service实现短信发送(转)
通过编程方式实现短信息的发送对很多人来说是一件比较烦杂的事情,目前一般的解决方法是通过计算机和手机的连线,通过可对手机编程的语言编写相关的手机短信息程序来实现,而这种方法对于一般人来说是很难达到的,因 ...
- 使用Carthage安装第三方Swift库
http://blog.crazyphper.com/?p=3661 carthage update
- 1.2 从 ACID 到 CAP/BASE
1.事务 事务(Tranction)是指,由一系列对系统中数据进行访问与更新操作,所组成的一个逻辑执行单元.狭义上的事务是指数据库事务. 事务有四个特性. 原子性:原子性要求事务只允讲有两种状态,全部 ...