• ASFNU SC Day6


    今天是暑期训练 第七 第六天(中间放了一天假)。

    学习字符串简单算法,kmp,AC自动机,trie树等。

    ----算法模板----

    KMP:随手打的,不知道能不能过。 

    void getnxt(char *W){
        memset(nxt,-1,sizeof nxt);
        int k=-1,wlen=strlen(W);
        for(int q=0;q<wlen;q++){
            while(k!=-1){
                if(W[q]==W[k]) break;
                k=nxt[k];
            }
            nxt[q+1]=++k;
        }
    }
    int KMP(char *W,char *T){
        int ans=0;
        int wlen=strlen(W),tlen=strlen(T);
        for(int i=0,j=0;i<=tlen;i++,j++){
            if(j==-1) continue;
            if(W[j]!=T[i]||j==wlen){
                ans+=(j==wlen?1:0);
                i--; j=nxt[j]-1;
                continue;
            }
        }
        return ans;
    }

     AC自动机,trie树:

    //trie树
    void add(char *s,int num){
        int len=strlen(s),x=0;
        val[0]='
    ';
        for(int pos=0;pos<len;pos++){
            if(!trie[x][s[pos]-'a']){
                trie[x][s[pos]-'a']=++cnt;
                val[cnt]=s[pos];
            }
            x=trie[x][s[pos]-'a'];
        }
        end[x]=num;
        return ;
    }
    //AC自动机
    queue <int> q;
    void bfs(){
        q.push(0);
        while(!q.empty()){
            int now=q.front();q.pop();
            for(int i=0;i<=25;i++){
                if(!trie[now][i]) continue;
                if(now==0){
                    q.push(trie[now][i]);
                    continue;
                }
                int j=fail[now];
                while(!trie[j][i]&&j)
                    j=fail[j];
                fail[trie[now][i]]=trie[j][i];
                q.push(trie[now][i]);
            }
        }
        return ;
    }
    void search(char *s){
        int x=0;
        int len=strlen(s);
        for(int pos=0;pos<=len;pos++){
            int j=x;
            while(j){
                if(j==fail[j]) exit(-1);
                if(end[j]) ans[end[j]]++;
                j=fail[j];
            }
            while(!trie[x][s[pos]-'a']&&x) x=fail[x];
            x=trie[x][s[pos]-'a'];
        }
        return ;
    }

    -----模拟赛&例题-----

    地址:https://cn.vjudge.net/contest/236074

    A.POJ 3461

      kmp裸题。

    B.POJ 2752

      有两种想法,但做法一样。

      一、看作自己与自己匹配,每次成功匹配的位置即是答案。

        (不必真的跑KMP,只需要递归加入答案即可)

      二、既然是找相同前缀后缀,那么最长的已经算出,第二长的就是最长的最长相同前缀后缀,以此类推。

        (和上一种实现方法相同)

      其实我认为,这两种想法的等价性就是KMP的精华所在。

    C.POJ 3080

      枚举第一个串的字串,然后看看它们是不是其它串的字串。

      原来复杂度是O(len^4*n)的,kmp优化后为O(len^3*n+n^2)

    D.POJ 2406

      我们发现,如果循环节存在,那么这个串的最长相同前缀后缀必然和原串只差一个循环节长。

      所以跑nxt后判断输出答案即可。

    E.HYSBZ 1030

      AC自动机上DP……

      开始写了一个dfs,获得10分。

      后来考虑优化,发现可以用dp[i][j]表示考虑i位,当前在j的方案数。

      接着我们又会发现如果存含可读单词的方案数在AC自动机上不好跑……

      所以存不含可读单词的,AC自动机上转移即可。

      最后用26^M-Σdp[M][i]即可。

    F.HDU 2222

      AC自动机裸题。去年居然RE了……

      教训:strlen不仅不能在循环里用,也不能在递归函数里用,要传参下去。

      T了数百次啊……

    附代码:

      以后有时间再放吧。

  • 相关阅读:
    Dice 5 ==> dice 7
    Dice 7 ==> dice 5
    100 floors 2 eggs
    Determine overlapping rectangles
    Product of integers
    Maximum profit of stocks
    样式表
    20170508
    2017年05月07
    The second day of school
  • 原文地址:https://www.cnblogs.com/JiuPleber/p/9251698.html
Copyright © 2020-2023  润新知