bzoj 3940 & 3942 KMP || AC自动机

来源:互联网 发布:网络教育有什么专业 编辑:程序博客网 时间:2024/06/11 00:19

3942题解:
定义f[i] 为S串以第i位结尾的后缀,最长可以是T串多长的前缀,这一个可以用KMP匹配。
可以用一个first数组记录i字符前一个未被匹配的位置是哪一个,当f[i]=len(T)时,就可以将最末尾的len(T)个字符匹配了。
3940只需要把KMP换为AC自动机就可以。

3942:

#include<cstdio>#include<cstring>#include<iostream>#define maxn 1000005using namespace std;char s1[maxn];char s2[maxn];int fail[maxn];void get_kmp(){    fail[1]=0;    int n=strlen(s2+1);    for(int i=2;i<=n;i++)    {        int p=fail[i-1];        while(p&&s2[p+1]!=s2[i]) p=fail[p];        if(s2[p+1]==s2[i]) fail[i]=p+1;    }}int fst[maxn];int cp[maxn];bool use[maxn];int find(int x){    if(use[fst[x]])        fst[x]=find(fst[x]);    return fst[x];}void work(){    int l1=strlen(s1+1);    int l2=strlen(s2+1);    for(int i=1;i<=l1;i++)        fst[i]=i-1;    for(int i=1;i<=l1;i++)    {        int p=cp[find(i)];        while(p&&s2[p+1]!=s1[i]) p=fail[p];        if(s2[p+1]==s1[i]) cp[i]=p+1;        if(cp[i]==l2)        {            int x=i;            for(int j=1;j<=l2;j++)                use[x]=1,x=find(x);        }    }}int main(){    scanf("%s",s1+1);    scanf("%s",s2+1);    get_kmp();work();    int l=strlen(s1+1);    for(int i=1;i<=l;i++)        if(!use[i]) putchar(s1[i]);    return 0;}

3940:

#include<queue>#include<cstdio>#include<cstring>#include<iostream>#define maxn 100005using namespace std;char s[maxn];char s1[maxn];bool use[maxn];int fst[maxn],cp[maxn];int find(int x){    if(use[fst[x]])        fst[x]=find(fst[x]);    return fst[x];}struct Trie{    int val[maxn];    int fail[maxn];    int deep[maxn];    int ch[maxn][27],cnt;    void insert()    {        int p=0;        int n=strlen(s+1);        for(int i=1;i<=n;i++)        {            int c=s[i]-'a'+1;            if(!ch[p][c]) ch[p][c]=++cnt;            p=ch[p][c];deep[p]=i;        }        val[p]++;    }    queue<int> Q;    void build()    {        for(int i=1;i<=26;i++)            if(ch[0][i]) Q.push(ch[0][i]);        while(!Q.empty())        {            int r=Q.front();Q.pop();            for(int i=1;i<=26;i++)            {                int u=ch[r][i];                if(!u)                {                    ch[r][i]=ch[fail[r]][i];                    continue;                }                Q.push(u);                int p=fail[r];                while(p&&!ch[p][i]) p=fail[p];                fail[u]=ch[p][i];            }        }    }    void work()    {        int l=strlen(s1+1);        for(int i=1;i<=l;i++)            fst[i]=i-1;        for(int i=1;i<=l;i++)        {            int p=cp[find(i)];            int c=s1[i]-'a'+1;            while(p&&!ch[p][c]) p=fail[p];            if(ch[p][c]) p=ch[p][c];            cp[i]=p;            if(val[p])            {                int x=i;                for(int j=1;j<=deep[p];j++)                    use[x]=1,x=find(x);            }        }    }}AC;int main(){    scanf("%s",s1+1);    int n;scanf("%d",&n);    for(int i=1;i<=n;i++)    {        scanf("%s",s+1);        AC.insert();    }    AC.build();    AC.work();    int l=strlen(s1+1);    for(int i=1;i<=l;i++)        if(!use[i]) putchar(s1[i]);    return 0;}
1 0