萌新感言:

我的天呐!

因为是AC自动机的专题所以没有管别的。。。硬着头皮吃那份题解(代码)。。【请戳简单美丽可爱的代码(没开玩笑)

首先讲AC自动机:

tag存的是以这个节点为后缀的字符串个数(已状压)。

我们在构造fail指针的时候,采用的是BFS的手段,对于树而言,那就是一层一层的向下遍历,

所以代码很巧妙(不能说巧妙吧,就是这样的),在找到fail位置的时候直接跳出,然后更新了tag,为什么可以这样?因为长的找到的时候,短的早就找过了,所以直接更新就好了。

然后这份代码有一个小瑕疵(讲错请吐槽!):因为在构造fail指针的时候tag已经更新过了,所以在DP的时候没必要再找到fail指针然后更新。

自身问题(可跳过):

还有构造fail的函数中当节点不存在的时候,这个节点的位置,用父节点的这个元素的fail指针取代了,如图:

道理还是一样,我要保证长的找到的时候,短的早就找过了。

然后讲DP:

感觉AC自动机下的DP很好理解,因为Trie树上本身对于每个节点就是一种种状态,用BFS的手段从上层到下层遍历。

DP[ i ][ j ]表示匹配到 i 节点,匹配到 j 个字符串时的最短步数。

每次只会伸展一个新节点,从而获取更多的后缀串,所以

dp[x][new_string_num]=min(dp[x][new_string_num],dp[x的父节点][old_string_num]+1);

that's all,thanks for watching....

//#include <bits/stdc++.h>
#include<iostream>
#include<queue>
#include<cstdio>
#include<string.h>
#include<algorithm>
using namespace std;
typedef pair<int,int> PII;
const int N=205;
const int INF=0x3f3f3f3f;
int n,dp[N][1030];
int g[N][4],fail[N],tag[N];
int sz; void init()
{
sz=1;
tag[0]=0;
memset(g[0],0,sizeof(g[0]));
} int GetID(char x)
{
if(x=='A') return 0;
if(x=='T') return 1;
if(x=='C') return 2;
return 3;
} void INS(char *str,int id)
{
int len=strlen(str),index,root=0;
for(int i=0;i<len;i++){
index=GetID(str[i]);
if(g[root][index]==0)
{
tag[sz]=0;
memset(g[sz],0,sizeof(g[sz]));
g[root][index]=sz++;
}
root=g[root][index];
}
tag[root]|=(1<<id);
} void Build_fail()
{
queue<int>que;
for(int i=0;i<4;i++)
{
int u=g[0][i];
if(u){
fail[u]=0;
que.push(u);
}
} while(!que.empty())
{
int root=que.front();
que.pop();
for(int i=0;i<4;i++){
int u=g[root][i];
if(!u){
g[root][i]=g[fail[root]][i];//如果这个节点不存在 用父节点的这个元素的fail指针取代了
continue;
}
que.push(u);
int v=fail[root];
while(v && g[v][i]==0)
v=fail[v];
fail[u]=g[v][i]; //构造
tag[u]|=tag[fail[u]]; //更新节点存的字符串个数。
}
}
} int solve()
{
//初始化
Build_fail();
memset(dp,INF,sizeof(dp));
dp[0][0]=0;
queue<PII>que;
que.push(make_pair(0,0));//塞入根节点,匹配0; while(!que.empty())
{
int u=que.front().first;
int s=que.front().second;
que.pop(); for(int i=0;i<4;i++){
int k=g[u][i]; //匹配这个节点,因为之前当节点不存在的时候已经存了父节点的该元素的fail指针,所以不用考虑为空
int ss=s|tag[k]; //在建立fail指针的时候,tag[k]存的字符串个数已经更新
if(dp[k][ss]>dp[u][s]+1)
{
dp[k][ss]=dp[u][s]+1;
que.push(make_pair(k,ss));
if(ss==(1<<n)-1)
return dp[k][ss];
}
}
}
return 0;
} int main()
{
int T;
char s[30];
scanf("%d",&T);
while(T--){
init();
scanf("%d",&n);
for(int i=0;i<n;i++)
{
scanf("%s",s);
INS(s,i);
}
printf("%d\n",solve());
}
return 0;
}

POJ1699【AC自动机+状压DP_感言】的更多相关文章

  1. hdu 2825 aC自动机+状压dp

    Wireless Password Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others ...

  2. hdu 6086 -- Rikka with String(AC自动机 + 状压DP)

    题目链接 Problem Description As we know, Rikka is poor at math. Yuta is worrying about this situation, s ...

  3. [BZOJ1559]密码 AC自动机+状压

    问题 K: [JSOI2009]密码 时间限制: 1 Sec  内存限制: 64 MB 题目描述 众所周知,密码在信息领域起到了不可估量的作用.对于普通的登陆口令,唯一的破解 方法就是暴力破解一逐个尝 ...

  4. bzoj 1212: [HNOI2004]L语言 AC自动机+状压

    为什么这道题网上所有题解写的都是N*Len的trie树的暴力啊,4E的复杂度... 为什么暴力还跑这么快啊TAT.. 有一个O(Len)的做法就是先把AC自动机建出来,因为每个字典串的长度很小,所以我 ...

  5. [HNOI2006]最短母串问题——AC自动机+状压+bfs环形处理

    Description 给定n个字符串(S1,S2,„,Sn),要求找到一个最短的字符串T,使得这n个字符串(S1,S2,„,Sn)都是T的子串. 32MB Input 第一行是一个正整数n(n< ...

  6. BZOJ1559 [JSOI2009]密码 【AC自动机 + 状压dp】

    题目链接 BZOJ1559 题解 考虑到这是一个包含子串的问题,而且子串非常少,我们考虑\(AC\)自动机上的状压\(dp\) 设\(f[i][j][s]\)表示长度为\(i\)的串,匹配到了\(AC ...

  7. UVALive - 4126 Password Suspects (AC自动机+状压dp)

    给你m个字符串,让你构造一个字符串,包含所有的m个子串,问有多少种构造方法.如果答案不超过42,则按字典序输出所有可行解. 由于m很小,所以可以考虑状压. 首先对全部m个子串构造出AC自动机,每个节点 ...

  8. [HNOI2006]最短母串 (AC自动机+状压)

    Description 给定n个字符串(S1,S2,„,Sn),要求找到一个最短的字符串T,使得这n个字符串(S1,S2,„,Sn)都是T的子串. Input 第一行是一个正整数n(n<=12) ...

  9. HDU 3247 Resource Archiver(AC自动机 + 状压DP + bfs预处理)题解

    题意:目标串n( <= 10)个,病毒串m( < 1000)个,问包含所有目标串无病毒串的最小长度 思路:貌似是个简单的状压DP + AC自动机,但是发现dp[1 << n][ ...

随机推荐

  1. 使用sed来自动注释/恢复crontab中的一个任务

    # 注释crontab任务crontab -l  >  ${WORK_DIR}/cron_binarysed  -i 's%\(.*/home/xyz/xyz.sh\)%#\1%' ${WORK ...

  2. 《TCP/IP具体解释卷2:实现》笔记--UDP:用户数据报协议

    用户数据报协议.即UDP,是一个面向数据报的简单运输层协议:进程的每次输出操作仅仅产生一个UDP数据报,从而发送 一个IP数据报. 进程通过创建一个Internet域内的SOCK_DGRAM类型的插口 ...

  3. 怎么样获得泛型T的Class对象?

    public class GenClass<T> { private Class<T> entityClass; } public class Test { public st ...

  4. LeetCode(82)题解: Remove Duplicates from Sorted List II

    https://leetcode.com/problems/remove-duplicates-from-sorted-list-ii/ 题目: Given a sorted linked list, ...

  5. c# 编程修改 wince 系统时间

    [StructLayout(LayoutKind.Sequential)] public struct SYSTEMTIME { public ushort wYear; public ushort ...

  6. EasyRTMP实现将RTSP流转换成RTMP流实现RTSP直播转RTMP直播的功能

    本文转自EasyDarwin开源团队Kim的博客:http://blog.csdn.net/jinlong0603/article/details/52951311 EasyRTMP EasyRTMP ...

  7. c# 怎么获取自己的IP地址

    1.aspx页面,asp.net项目的页面 <%@ Page Language="C#" AutoEventWireup="true" CodeBehin ...

  8. parameters arguments 形式参数 实际参数

    parameter和argument的区别 – 笑遍世界 http://smilejay.com/2011/11/parameter_argument/ https://en.wikipedia.or ...

  9. eclipse中怎么删除重复的console

    eclipse中不同的应用会开启不同的console,所以并不是重复. 如图: Terminate标志/操作按钮,可以停止当前的执行,以及标志此Console是Terminated状态: Remove ...

  10. eclipse集成SVN插件-----复制添加插件

    首先从网上下载一个svn的插件包, 将插件包解压, 打开eclipse的文件夹, 将svn插件中features文件夹中的jar复制到eclipse中features文件夹中去: 将svn插件中plu ...