AC自动机 fail树 线段树维护

http://codeforces.com/problemset/problem/163/E

http://acm.hdu.edu.cn/showproblem.php?pid=4117

上面两题我都是用AC自动机 + 线段树写的

当我们用AC自动机解决DP 或者 统计问题的时候,如果要支持更新操作,就需要数据结构的帮忙了

比如codeforces 163E,背景是最简单的多串匹配,但是有一个特殊的地方是会删除一些字符串和重新恢复一些字符串,注意到我们在统计的时候其实就是沿着fail指针走,把所有的标记叠加起来,而fail指针构成了一棵fail树,所以我们在求当前节点的fail指针方向有多少个标记的时候不必一层层的fail上去了,对于每个点维护其到根的有效节点的个数即可,

当更新某个点的时候,就相当于这个点的子树到根的有效节点的个数都发生了变化,将树形结构变成线性结构,在线段树中更新即可


第二题是个DP题,也是类似的方法,在fail指针方向找一个最大的值进行DP的转移,利用线段树求极值


codeforces 163E

#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
using namespace std;
#define lowbit(x) ((x)&(-(x)))
#define sqr(x) ((x)*(x))
#define PB push_back
#define MP make_pair
typedef long long lld;
typedef vector VI;
typedef vector VS;
typedef pair PII;
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
const int inf = ~0u>>2;
const int maxn = 1000010;
// ~ segment tree
int add[maxn<<2];
int sum[maxn<<2];
int L[maxn],R[maxn];
//AC auto
const int M = maxn;
const int CD = 26;
int sz;
int ID[128];
int val[M];
int fail[M];
int Q[M];
int ch[M][CD];
int mp[M];
//failtree
vector edge[maxn];
int tot;
void Init()
{
	fail[0]=0;  val[0]=0;
	sz=1;
	memset(ch[0],0,sizeof(ch[0]));
	for(int i=0;i<26;i++) ID[i+'a']=i;
}
void Insert(char *s,int id){
	int p=0;
	for( ; *s ; s++)	{
		int c=ID[*s];
		if(!ch[p][c])  {
			memset(ch[sz],0,sizeof(ch[sz]));
			val[sz] = 0;
			ch[p][c] = sz++;
		}
		p=ch[p][c];
	}
	val[p] = 1;
	mp[id] = p;
}
void Construct() {
	int *s=Q,*e=Q;
	for(int i=0;i>1;
	build(lson);
	build(rson);
}
void pushdown(int rt,int m)
{
	if(add[rt])
	{
		add[rt<<1] += add[rt];
		add[rt<<1|1] += add[rt];
		sum[rt<<1] += add[rt] * (m-(m>>1));
		sum[rt<<1|1] += add[rt]*(m>>1);
		add[rt]=0;
	}
}
void pushup(int rt)
{
	sum[rt] = sum[rt<<1] + sum[rt<<1|1];
}
void update(int L,int R,int v,int l,int r,int rt)
{
	if(L <= l && r <= R)
	{
		add[rt] += v;
		sum[rt] += v;
		return ;
	}
	pushdown(rt,r-l+1);
	int m=l+r>>1;
    if(L <= m) update(L , R , v , lson);
	if(R > m)  update(L , R , v , rson);
	pushup(rt);
}
int query(int p,int l,int r,int rt)
{
	if(l == r)
	{
		return  sum[rt];
	}
	pushdown(rt,r-l+1);
	int m = l+r>>1;
	if(p <= m) return query(p,lson);
	if(p > m) return query(p,rson);
}
void failtree_init()
{
	tot=0;
	for(int i=1;i

hdu 4117

#include
#include
#include
#include
using namespace std;
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
inline void Max(int &a,int b){if(b>a) a=b;}
const int M  =  300010;
const int N  =  20010;
const int CD = 26;
int fail[M];
int Q[M];
int ch[M][CD];
int ID[128];
int sz;
char S[M];
int node[M];
void Init(){
    fail[0]=0;
    memset(ch[0],0,sizeof(ch[0]));
    sz=1;
    for(int i=0;i<26;i++) ID[i+'a'] = i;
}
void Insert(char *s,int id) {
     int p=0;
     for(;*s;s++) {
         int c=ID[*s];
         if(!ch[p][c]) {
             memset(ch[sz],0,sizeof(ch[sz]));
             ch[p][c]=sz++;
         }
         p=ch[p][c];
     }
     node[id]=p;
}
void Construct(){
    int *s=Q,*e=Q,v;
    for(int i=0;i edge[M];
int n;
int pos[N];
int tot;
int mx[M<<2];
int lz[M<<2];
void pushup(int rt) {
    mx[rt] = max(mx[rt<<1],mx[rt<<1|1]);
}
void pushdown(int rt) {
     if(lz[rt]) {
        Max(lz[rt<<1],lz[rt]);
        Max(lz[rt<<1|1],lz[rt]);
        Max(mx[rt<<1],lz[rt<<1]);
        Max(mx[rt<<1|1],lz[rt<<1|1]);
        lz[rt]=0;
     }
}
void build(int l,int r,int rt) {
    lz[rt] = mx[rt] = 0;
    if(l==r) return ;
    int m=l+r>>1;
    build(lson);
    build(rson);
}
void update(int L,int R,int val,int l,int r,int rt) {
    if(L <= l && r <= R) {
        Max(lz[rt],val);
        Max(mx[rt],val);
        return ;
    }
    pushdown(rt);
    int m=l+r>>1;
    if(L <= m) update(L,R,val,lson);
    if(R > m) update(L,R,val,rson);
    pushup(rt);
}
int query(int pos,int l,int r,int rt) {
    if(l==r) {
        return mx[rt];
    }
    pushdown(rt);
    int m=l+r>>1;
    if(pos <= m) return query(pos,lson);
    return query(pos,rson);
}
int L[M],R[M],dp[M];
void dfs(int u){
    L[u]=++tot;
    for(int i=0;i0) AC(i,pos[i-1]+1,pos[i]);
            Max(ans,dp[i]);
        }
        printf("Case #%d: %d\n",ca++,ans);
    }
    return 0;
}



你可能感兴趣的:(Data,Structures,Dynamic,Programming,Strings)