UVa 1449 - Dominating Patterns (AC自动机)

题目大意:给出多个字符串模板,并给出一个文本串,求在文本串中出现最多的模板,输出最多的次数并输出该模板(若有多个满足,则按输入顺序输出)。

思路:赤裸裸的 AC自动机,上模板。

代码:

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<queue>
#include<algorithm>
#include<cmath>
#include<map>
using namespace std;
#define INF 0x7fffffff

char s[160][80],T[1000010];
int nz,cnt,ch[15000][30],num[160],val[315000];
int f[315000],last[315000];

void insert(char a[],int k){
    int i,j,len = strlen(a),u = 0;
    for(i=0;i<len;i++){
        int v = a[i] - 'a' ;
        if(!ch[u][v]){
            memset(ch[nz],0,sizeof(ch[nz]));
            val[nz]=0;
            ch[u][v] = nz++;
        }
        u = ch[u][v];
    }
    val[u] = k;
}

void getFail(){
    int i;
    queue<int> Q;
    while(!Q.empty())
        Q.pop();
    f[0] = 0;
    for(i=0;i<26;i++)
        if(ch[0][i]){
            f[ch[0][i]] = 0;
            Q.push(ch[0][i]);
            last[ch[0][i]] = 0; 
        }
    while(!Q.empty()){
        int r = Q.front();
        Q.pop();
        for(i=0;i<26;i++){
            int v = ch[r][i];
            if(v){
                Q.push(v);
                int p = f[r];
                while(p && !ch[p][i])
                    p = f[p];
                f[v] = ch[p][i];
                last[v] = val[f[v]] ? f[v] : last[f[v]];
            }
        }
    }
}

void print(int i){
    if(i){
//      printf("%d ",val[i]); 
        num[val[i]]++;
        print(last[i]);
    }
}

void find(){
    int i,j;
    int len = strlen(T);
    int u = 0;
    for(i=0;i<len;i++){
        int v = T[i] - 'a';
        while(u && !ch[u][v]) u = f[u];
        u = ch[u][v];
        if(val[u]) print(u);
        else if(last[u]) print(last[u]);
    } 
}

int main(){
    int n,i,j;
    while(scanf("%d",&n) && n){
        nz = 1;
        memset(val,0,sizeof(val));
        memset(ch[0],0,sizeof(ch));
        memset(num,0,sizeof(num));
        for(i=1;i<=n;i++){
            scanf("%s",s[i]);
            insert(s[i],i);
        }
        scanf("%s",T);
        getFail();
        find();
        int MAX = 0;
        for(i=1;i<=n;i++)
            MAX = max(MAX,num[i]);
        printf("%d\n",MAX);
        for(i=1;i<=n;i++)
            if(num[i] == MAX)
                printf("%s\n",s[i]);
    }

    return 0;
}

转载于:https://www.cnblogs.com/jxgapyw/p/4780584.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值