1. 程式人生 > >暑假集訓day9

暑假集訓day9

esp poj char ace ora ac自動機 trie 模板題 ostream

今天主要將講與字符串有關的吧。

1.trie樹

Remember the Word(LA_3942)

trie樹的模板題了。如果trie樹不知道可以看藍書(算法競賽入門經典第一版)(以下的KMP和AC自動機都可以在此書上看到)。

#include<cstring>
#include<vector>
#include<cstdio>
#include<iostream>
using namespace std;
const int mn=400010,mod=20071027;char ch[300010],w[101];
int T[mn][26],val[mn],sz=1
,d[300010],len[4010],S,cnt=0; void add(char *s,int v){ int u=0,l=strlen(s); for(int i=0;i<l;i++){ int c=(int)(s[i]-a); if(!T[u][c]){ memset(T[sz],0,sizeof(T[sz])); val[sz]=0;T[u][c]=sz++; }u=T[u][c]; }val[u]=v; } void find(char *s,int len,vector<int
>& ans){ int u=0;for(int i=0;i<len;i++){ if(s[i]==\0)break;int c=(int)(s[i]-a); if(!T[u][c])break;u=T[u][c]; if(val[u])ans.push_back(val[u]); } } int main(){ while(scanf("%s%d",ch,&S)!=EOF){ sz=1;memset(T[0],0,sizeof(T[0])); for(int i=1
;i<=S;i++){scanf("%s",w);len[i]=strlen(w);add(w,i);} memset(d,0,sizeof(d));int l=strlen(ch);d[l]=1; for(int i=l-1;i>=0;i--){ vector<int>p;find(ch+i,l-i,p); for(int j=0;j<p.size();j++)d[i]=(d[i]+d[i+len[p[j]]])%mod; } printf("Case %d: %d\n",++cnt,d[0]); }return 0; }

2.KMP

這個算法比較難理解,但是很好記,效率O(n+m)。

Oulipo(poj_3461)

#include<cstring>
#include<vector>
#include<cstdio>
#include<iostream>
using namespace std;
int f[10010],ans;char w[10010],t[1000010];
void getfail(){
    f[0]=f[1]=0;int m=strlen(w);
    for(int i=1;i<m;i++){
        int j=f[i];
        while(j&&w[i]!=w[j])j=f[j];
        f[i+1]=(w[i]==w[j]?j+1:0);
    }
}
void find(){
    getfail();int j=0,n=strlen(t),m=strlen(w);
    for(int i=0;i<n;i++){
        while(j&&w[j]!=t[i])j=f[j];
        if(w[j]==t[i])j++;if(j==m)ans++;
    }
}
int main()
{
    int n;scanf("%d",&n);
    while(n--){
        memset(f,0,sizeof(f));ans=0;
        scanf("%s%s",w,t);find();
        printf("%d\n",ans);
    }
    return 0;
}

Period(poj_1961)

#include<cstring>
#include<cstdio>
#include<iostream>
using namespace std;
const int mk=1000010;
char c[mk];int k,f[mk],cnt=0;
void getfail(){
    f[0]=f[1]=0;
    for(int i=1;i<k;i++){
        int j=f[i];
        while(j&&c[i]!=c[j])j=f[j];
        f[i+1]=(c[i]==c[j]?j+1:0);
    }
}
int main()
{
    scanf("%d",&k);
    while(k){
        scanf("%s",c);
        getfail();printf("Test case #%d\n",++cnt);
        for(int i=2;i<=k;i++)
            if(f[i]&&i%(i-f[i])==0)
                printf("%d %d\n",i,i/(i-f[i]));
        puts("");scanf("%d",&k);
    }
    return 0;
}

Power Strings(poj_2406)

#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
const int N=1000010;
int f[N],k;char c[N];
void getfail(){
    f[0]=f[1]=0;
    for(int i=1;i<k;i++){
        int j=f[i];
        while(j&&c[i]!=c[j])j=f[j];
        f[i+1]=(c[i]==c[j]?j+1:0);
    }
}
int main()
{
    while(1){
        scanf("%s",c);
        if(c[0]==.)break;
        k=strlen(c);getfail();
        if(f[k]&&k%(k-f[k])==0)printf("%d\n",k/(k-f[k]));
        else puts("1");
    }
    return 0;
}

3.AC自動機(aho-corasick自動機)

本算法是結合了以上的trie樹和KMP算法。

(暫缺)。

本文由Yzyet編寫,網址為www.cnblogs.com/Yzyet。非Yzyet同意,禁止轉載,侵權者必究。

暑假集訓day9