AC自动机+DP

#include <cstdio>
#include <queue>
#include <cstring>
using namespace std; #define D(x) const int MAX_D_LEN = ;
const int MAX_LEN = ;
const int MAX_N = ;
const int MAX_CHILD_NUM = ;
const int MAX_NODE_NUM = MAX_N * MAX_D_LEN;
const int INF = 0x3f3f3f3f; char dna[MAX_LEN]; struct Trie
{
int next[MAX_NODE_NUM][MAX_CHILD_NUM];
int fail[MAX_NODE_NUM];
bool disease[MAX_NODE_NUM];
int node_cnt;
bool vis[MAX_NODE_NUM]; //set it to false
int root;
int dp[MAX_LEN][MAX_NODE_NUM]; void init()
{
node_cnt = ;
root = newnode();
memset(vis, , sizeof(vis));
} int newnode()
{
for (int i = ; i < MAX_CHILD_NUM; i++)
next[node_cnt][i] = -;
disease[node_cnt++] = false;
return node_cnt - ;
} int get_id(char a)
{
return (int)a;
} 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];
}
disease[now] = true;
} 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];
if (disease[fail[next[now][i]]])
disease[next[now][i]] = true;
Q.push(next[now][i]);
}
}
} int work(char* dna)
{
int len = strlen(dna);
for (int i = ; i < node_cnt; i++)
{
if (disease[i])
dp[len][i] = INF;
else
dp[len][i] = ;
}
for (int i = len - ; i >= ; i--)
{
int key = get_id(dna[i]);
for (int j = ; j < node_cnt; j++)
{
if (disease[j])
continue;
dp[i][j] = dp[i + ][root] + ;
int v = next[j][key];
if (disease[v])
continue;
dp[i][j] = min(dp[i][j], dp[i + ][v]);
}
}
return dp[][root];
} void debug()
{
for(int i = ;i < node_cnt;i++)
{
printf("id = %3d,fail = %3d,end = %3d,chi = [",i,fail[i],disease[i]);
for(int j = ;j < MAX_CHILD_NUM;j++)
printf("%2d",next[i][j]);
printf("]\n");
}
}
}ac; int n, m;
char st[MAX_LEN]; int main()
{
while (scanf("%d %d", &n, &m), n | m)
{
ac.init();
for (int i = ; i < n; i++)
{
scanf("%s", st);
getchar();
ac.insert(st);
}
ac.build();
int ans = ;
for (int i = ; i < m; i++)
{
gets(st);
ans += ac.work(st);
}
printf("%d\n", ans);
}
return ;
}

hnu11187的更多相关文章

随机推荐

  1. 50多条mysql数据库优化建议

    1.对查询进行优化,应尽量避免全表扫描,首先应考虑在 where 及 order by 涉及的列上建立索引. 缺省情况下建立的索引是非群集索引,但有时它并不是最佳的.在非群集索引下,数据在物理上随机存 ...

  2. 使用jQuery的Scrollify插件实现鼠标滚轮或者手势滑动到页面下一节点部分

    有时我们需要做一个单页面介绍产品特性,而单页面内容非常多且页面非常长,为了快速定位到产品特性节点,我们使用js侦听用户滚轮事件,当用户触发滚轮滑动或者使用手势触屏滑动时,即可定位到相应的节点.一款jQ ...

  3. php操作mysql数据库

    <span style="font-family:Arial,Helvetica,sans-serif">在php操作数据库过,会频繁对数据库进行各种操作,所以,php ...

  4. jquery+css3实现3d滚动旋转

    最近有个漂亮妹子一直在向我推销潭州的视频,BUT我以前就看了一次觉得挺水的,就对那个妹子表示吾孤高.你们那玩意没意义的很弱.然后那个漂亮妹子锲而不舍的对我发链接,这个效果会吗,这个幻灯会写吗...我也 ...

  5. 详细介绍如何在win7下首次实现通过Git bash向Github提交项目

    详细介绍如何在win7下首次实现通过Git bash向Github提交项目 引自:http://jingpin.jikexueyuan.com/article/35944.html 作者: wddoe ...

  6. Linux下查看文件内容的命令

    查看文件内容的命令: cat     由第一行开始显示内容,并将所有内容输出 tac     从最后一行倒序显示内容,并将所有内容输出 more    根据窗口大小,一页一页的现实文件内容 less ...

  7. 绿书模拟day10 单词前缀

    [题目描述]一组单词是安全的,当且仅当不存在一个单词是另一个单词的前缀,这样才能保证数据不容易被误解,现在你手上有一个单词集合s,你需要计算有多少个自己是安全的.注意空集永远是安全的.[输入格式]第一 ...

  8. golang的json操作

    package main import ( "encoding/json" "fmt" "os" ) type ConfigStruct s ...

  9. Hadoop 之Hbase命令

    一.常用命令:(hbase shell 进入终端) 1.创建表: create 'users','user_id','address','info' 表users,有三个列族user_id,addre ...

  10. Java之异常处理机制

    来源:深入理解java异常处理机制 2.Java异常    异常指不期而至的各种状况,如:文件找不到.网络连接失败.非法参数等.异常是一个事件,它发生在程序运行期间,干扰了正常的指令流程.Java通 ...