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. C语言中的参数传递

    有空看看: c语言 函数传输传递的三种方式(值.指针.引用) C语言之参数传递 C语言形参和实参,传值调用和引用调用的区别

  2. JAVA日期加减运算

    1.用java.util.Calender来实现 Calendar calendar=Calendar.getInstance();      calendar.setTime(new Date()) ...

  3. dubbo框架----初探索-配置

    使用框架版本 dubbo-2.5.3 spring-4.2.1.RELEASE jdk-1.8 tomcat-8.0 zookeeper-3.3.6 Dubbo与Zookeeper.SpringMVC ...

  4. jQuery源码-jQuery.fn.attr与jQuery.fn.prop

    jQuery.fn.attr.jQuery.fn.prop的区别 假设页面有下面这么个标签,$('#ddd').attr('nick').$('#ddd').prop('nick')分别会取得什么值? ...

  5. 基于zepto判断mobile的横竖屏状态

    借用jquery mobile中的代码,删除了一些多余的部分,简单的基于zepto的模块 var CheckOrientation = (function(){ var win = $( window ...

  6. 字符编码详解及由来(UNICODE,UTF-8,GBK)

        一直对字符的各种编码方式懵懵懂懂,什么ANSI.UNICODE.UTF-8.GB2312.GBK.DBCS.UCS--是不是看的很晕,假如您细细的阅读本文你一定可以清晰的理解他们.Let's ...

  7. Ionic 常见问题及解决方案

    前言 Ionic是目前较为流行的Hybird App解决方案,在Ionic开发过程中会遇到很多常见的开发问题,本文尝试对这些问题给出解决方案. 一些常识与技巧 list 有延迟,可以在ion-cont ...

  8. 【PHP面向对象(OOP)编程入门教程】11.类的继承

    继承作为面向对象的三个重要特性的一个方面,在面向对象的领域有着及其重要的作用,好像没听说哪个面向对象的语言不支持继承. 继承是PHP5面象对象程序设计的重要特性之一,它是指建立一个新的派生类,从一个或 ...

  9. Apache常用2种工作模式prefork和worker比较

    Apache两种常用工作模式:prefork和worker. prefork MPM prefork是一个非线程型的.预派生的MPM,使用多个进程,每个进程在某个确定的时间只单独处理一个连接,效率高, ...

  10. js null和undefined

    在JavaScript开发中,被人问到:null与undefined到底有啥区别? 一时间不好回答,特别是undefined,因为这涉及到undefined的实现原理. 总所周知:null == un ...