AC自动机+状态压缩DP

注意:相同的串可能出现多次,如果匹配成功则将各次权值加和。

#include <cstdio>
#include <queue>
#include <cstring>
using namespace std; #define D(x) const int MAX_N = ;
const int MAX_LEN = ;
const int MAX_CHILD_NUM = ;
const int MAX_NODE_NUM = MAX_LEN * MAX_N; //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 == 'T')
return ;
if (a == 'C')
return ;
return ;
} void insert(char buf[], int id)
{
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] |= ( << id);
} 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; const int MAX_STATUS = ( << ) + ; int n, len;
char st[MAX_LEN];
int w[MAX_N];
bool dp[][MAX_NODE_NUM][MAX_STATUS]; int cal(int status)
{
int ret = ;
for (int i = ; i < n; i++)
{
if (status & ( << i))
ret += w[i];
}
return ret;
} int work()
{
int ret = -;
memset(dp, , sizeof(dp));
dp[][ac.root][] = true;
for (int i = ; i < len; i++)
{
for (int j = ; j < ac.node_cnt; j++)
for (int status = ; status < ( << n); status++)
dp[(i + ) & ][j][status] = false;
D(printf("%d\n", dp[(i + ) & ][][]));
for (int j = ; j < ac.node_cnt; j++)
{
for (int status = ; status < ( << n); status++)
{
if (!dp[i & ][j][status])
continue;
for (int k = ; k < ; k++)
{
int v = ac.next[j][k];
dp[(i + ) & ][v][status | ac.count[v]] = true;
D(printf("%d %d\n", j, status));
D(printf("%d %d %d %d\n", (i + ) & , v, status | ac.count[v], dp[(i + ) & ][][]));
}
}
}
}
for (int i = ; i < ac.node_cnt; i++)
for (int status = ; status < ( << n); status++)
{
if (dp[len & ][i][status])
{
if (dp[len & ][i][] && status == )
{
D(printf("*%d %d\n", i, ac.count[i]));
}
ret = max(ret, cal(status));
}
}
return ret;
} int main()
{
while (scanf("%d%d", &n, &len) != EOF)
{
ac.init();
for (int i = ; i < n; i++)
{
scanf("%s%d", st, &w[i]);
ac.insert(st, i);
}
ac.build();
int ans = work();
if (ans < )
puts("No Rabbit after 2012!");
else
printf("%d\n", ans);
}
return ;
}

zju3545的更多相关文章

随机推荐

  1. Mysql函数:Last_insert_id()语法讲解

    Mysql函数可以实现许多我们需要的功能,下面介绍的Mysql函数Last_insert_id()就是其中之一,希望对您学习Mysql函数能有所帮助. 自动返回最后一个INSERT或 UPDATE 查 ...

  2. [js/jquery]移动端手势拖动,放大,缩小预览图片

    摘要 有这样的需求需要在手机端预览图片的时候,实现图片的手势拖动,放大缩小功能.最终通过touch.js这个插件实现了效果. touch.js Touch.js是移动设备上的手势识别与事件库, 由百度 ...

  3. 黄永成-thinkphp讲解-个人博客讲解25集

    整个网站的根目录用blog你要跟别人说起,自己好识别的文件夹名字. 下面的项目名称 就不再重复的写了, 直接用App就好了. 网站访问: ...../index.php(入口文件)/Admin(模块名 ...

  4. mysql tinyint

    在MySQL的数据类型中,Tinyint的取值范围是:带符号的范围是-128到127.无符号的范围是0到255(见官方<MySQL 5.1参考手册>http://dev.mysql.com ...

  5. 使用MVVM框架avalon.js实现一个简易日历

    最近在做公司内部的运营管理系统,因为与日历密切相关,同时无需触发条件直接显示在页面上,所以针对这样的功能场景,我就用avalon快速实现了一个简易日历,毕竟也是第一次造日历这种轮子,所以这里记录下我当 ...

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

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

  7. WCF--提示:异常消息为“传入消息的消息格式不应为“Raw”。此操作的消息格式应为 'Xml', 'Json'。

    Ajax调用WCF服务... 本来用 // $.getJSON("http://localhost:16625/Service1.svc/Article_GetInfo", { } ...

  8. ASP FORM表单提交判断

    ASP提交表单是先进行Form填写检测,检测完成没问题之后再执行写入数据库表操作. 相关源码: <script language="javascript"> funct ...

  9. 安装cocoods

    http://www.tuicool.com/articles/7VvuAr3 http://blog.csdn.net/gf771115/article/details/50403253(详细,用终 ...

  10. 创业15条经验总结:温饱之后,创业公司CEO如何树“三观”?

    都说创业改变命运,事实上不是,创业,时时刻刻,可能连“命”都保不住!创业公司最重要的只有“活下去”.满足了这个.才有资格谈其他.公司连饭都开不了,还谈什么其他?创业公司如果连生存问题都解决不了,高位的 ...