ASFNU SC Day6

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

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

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

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]){
            i--;
            j=nxt[j]-1;
            continue;
        }
        if(j==wlen-1){
            ans++;
            j=nxt[wlen]-1;
            continue;
        }
    }
    return ans;
}

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

地址: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了数百次啊……

附代码:

  以后有时间再放吧。

猜你喜欢

转载自www.cnblogs.com/JiuPleber/p/9251698.html
sc"
sc