字符串

Posted 2016gdgzoi509

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了字符串相关的知识,希望对你有一定的参考价值。

题目

Description
技术图片
Input
技术图片

Output
技术图片

题解

显然用是AC自动机来解决

先说一下没人写的正解
二进制分组, 建\\(O(lgm)\\)个AC自动机。 定义AC自动机的size为这个AC自动机中的字符串个数。 当两个AC自动机size相等时合并这两个AC自动机。时间复杂度\\(O(mlgm)\\)

下面是比较好想, 也比较常规的做法。
题目中说强制在线, 但是却没有给字符串加密。 于是我们不一定要真的在线做。 我们可以用输入中出现的所有字符串建一个AC自动机, 虽然这样会把询问串也包含在内但对结果没有影响。
每次查询还是正常的在AC自动机上走。但由于是动态修改, 我们无法像正常的AC自动机一样预处理, 于是我们需要维护fail树。
把所有fail边拿出来建建一颗树。 然后问题转化成了: 修改一个点的权值, 询问一个点到根路径的权值和。 然后随便用数据结构维护就好了。

代码

#include <iostream>
#include <cstdlib>
#include <cstdio>
#include <cstring>
#include <algorithm>

#include <queue>

using namespace std;


typedef long long LL;


const int N = 1000010, M = 2000010;


int ed[N];


struct AC

    static const int SIZE = 1000010;
    
    int nxt[SIZE][26], fail[SIZE];
    LL val[SIZE];
    int root;
    int sz;

    AC()  

    void init()
    
        sz = 0;
        root = newnode();
    

    int newnode()
    
        memset(nxt[sz], 0, sizeof(nxt[sz]));
        fail[sz] = 0;
        val[sz] = 0;
        return sz++;
    
    
    void insert(char * str, int len, int id)
    
        int u = root;
        
        for (int i = 0; i < len; i++)
        
            int c = str[i] - 'a';
            if (!nxt[u][c])
                nxt[u][c] = newnode();
            u = nxt[u][c];
        
        
        ed[id] = u;
    

    void getFail()
    
        queue <int> q;
        
        for (int i = 0; i < 26; i++)
            if (nxt[root][i])
            
                fail[nxt[root][i]] = root;
                q.push(nxt[root][i]);
            
            else nxt[root][i] = root;
        
        while (!q.empty())
        
            int x = q.front(); q.pop();
            for (int i = 0; i < 26; i++)
            
                if (nxt[x][i])
                
                    fail[nxt[x][i]] = nxt[fail[x]][i];
                    q.push(nxt[x][i]);
                
                else nxt[x][i] = nxt[fail[x]][i];
            
        
    
 ac;


struct edge

    int from, to;
    edge()  
    edge(int _1, int _2) : from(_1), to(_2)  
 edges[M];

int head[N], nxt[M], tot;

inline void init()

    memset(head, -1, sizeof(head));
    tot = 0;


inline void add_edge(int x, int y)

    edges[tot] = edge(x, y);
    nxt[tot] = head[x];
    head[x] = tot++;
    edges[tot] = edge(y, x);
    nxt[tot] = head[y];
    head[y] = tot++;



int dfn[N], idf[N], siz[N], dfs_clock;

void dfs(int x, int fa)

    dfn[x] = ++dfs_clock;
    idf[dfn[x]] = x;
    siz[x] = 1;
    
    for (int i = head[x]; ~i; i = nxt[i])
    
        edge & e = edges[i];
        if (e.to != fa)
        
            dfs(e.to, x);
            siz[x] += siz[e.to];
        
    



struct Calc

    LL val[N];

    void upd(int x, int v)
    
        for (int i = x; i <= dfs_clock; i += (i & -i))
            val[i] += v;
    

    LL qry(int x)
    
        LL Ans = 0;
        for (int i = x; i > 0; i -= (i & -i))
            Ans += val[i];
        return Ans;
    
 Calc;


int m;


int opt[N];


char str[N];
int L[N], R[N];


int main()

    scanf("%d", &m);
    
    ac.init();
    
    for (int i = 1; i <= m; i++)
    
        scanf("%d", &opt[i]);
        L[i] = R[i-1] + 1;
        scanf("%s", str + L[i]);
        R[i] = L[i] + strlen(str + L[i]) - 1;
        ac.insert(str + L[i], R[i] - L[i] + 1, i);
    
    
    ac.getFail();
    
    init();
    
    for (int i = 1; i < ac.sz; i++)
        add_edge(ac.fail[i], i);
    
    dfs(0, -1);
    
    int mask = 0;
    
    for (int i = 1; i <= m; i++)
    
        opt[i] ^= mask;
        if (opt[i] == 1)
        
            int x = ed[i];
            int l = dfn[x], r = dfn[x] + siz[x] - 1;
            Calc.upd(l, 1);
            Calc.upd(r + 1, -1);
        
        else if (opt[i] == 2)
        
            int x = ed[i];
            int l = dfn[x], r = dfn[x] + siz[x] - 1;
            Calc.upd(l, -1);
            Calc.upd(r + 1, 1);
        
        else
        
            LL Ans = 0;
            int u = ac.root;
            for (int j = L[i]; j <= R[i]; j++)
            
                u = ac.nxt[u][str[j] - 'a'];
                Ans += Calc.qry(dfn[u]);
            
            mask ^= abs(Ans);
            printf("%lld\\n", Ans);
        
    
    
    return 0;

以上是关于字符串的主要内容,如果未能解决你的问题,请参考以下文章

第15章:字符串

什么是字符串常量和字符串变量啊???

neo4j字符串操作大全

java中怎么判断一个字符串数组中包含某个字符或字符串

PHP字符串函数

如何获取一个字符串在某个字符串的位置