uva1449 Dominating Patterns

78 篇文章 0 订阅

For each pre x of a given string S with N characters (each character
has an ASCII code between 97 and 126, inclusive), we want to know
whether the pre x is a periodic string. That is, for each i (2 i N
) we want to know the largest K > 1 (if there is one) such that the
pre x of S with length i can be written as A K , that is A
concatenated K times, for some string A . Of course, we also want to
know the period K . Input The input le consists of several test
cases. Each test case consists of two lines. The rst one contains N
(2 N 1000000) the size of the string S . The second line contains
the string S . The input le ends with a line, having the number zero
on it. Output For each test case, output ` Test case # ’ and the
consecutive test case number on a single line; then, for each pre x
with length i that has a period K > 1, output the pre x size i and the
period K separated by a single space; the pre x sizes must be in
increasing order. Print a blank line after each test case.

AC自动机模板题。

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int ss=26;
int son[11010][30],last[11010],cnt[11010],fail[11010],num[160],n,tot,l[160],len,que[11010];
char s[160][80],str[1000010];
bool have[11010];
void init()
{
    int i;
    for (i=1;i<=n;i++)
    {
        scanf("%s",s[i]+1);
        l[i]=strlen(s[i]+1);
    }
    scanf("%s",str+1);
    len=strlen(str+1);
    memset(son,0,sizeof(son));
    memset(fail,0,sizeof(fail));
    memset(cnt,0,sizeof(cnt));
    memset(have,0,sizeof(have));
    memset(last,0,sizeof(last));
    tot=0;
}
void build()
{
    int i,j,p,hd,tl,u;
    for (i=1;i<=n;i++)
    {
        p=0;
        for (j=1;j<=l[i];j++)
        {
            if (!son[p][s[i][j]-'a']) son[p][s[i][j]-'a']=++tot;
            p=son[p][s[i][j]-'a'];
        }
        num[i]=p;
        have[p]=1;
    }
    hd=tl=1;
    que[1]=0;
    while (hd<=tl)
    {
        u=que[hd++];
        if (have[fail[u]]) last[u]=fail[u];
        else last[u]=last[fail[u]];
        for (i=0;i<ss;i++)
          if (son[u][i])
          {
            if (u) fail[son[u][i]]=son[fail[u]][i];
            que[++tl]=son[u][i];
          }
          else son[u][i]=son[fail[u]][i];
    }
}
void add(int p)
{
    if (!p) return;
    cnt[p]++;
    add(last[p]);
}
void solve()
{
    int i,p;
    p=0;
    for (i=1;i<=len;i++)
    {
        p=son[p][str[i]-'a'];
        if (have[p]) add(p);
        else add(last[p]);
    }
}
void out()
{
    int i,ans=0;
    for (i=1;i<=n;i++)
      ans=max(ans,cnt[num[i]]);
    printf("%d\n",ans);
    for (i=1;i<=n;i++)
      if (cnt[num[i]]==ans) printf("%s\n",s[i]+1);
}
int main()
{
    while (scanf("%d",&n)&&n)
    {
        init();
        build();
        solve();
        out();
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值