hdu 4333 Revolving Digits

    扩展kmp,先把原串翻一倍,然后构造原串的next数组,通过原串和原串翻倍的串构造extend数组,需要注意的是还要计算原串翻倍的串的循环节不然会超时!最后附上大神yefeng1627的扩展kmp的详细讲解及模板的博客(http://www.cnblogs.com/yefeng1627/archive/2012/12/24/2830979.html);

#include<stdio.h>
#include<string.h>
int next[200005],ext[200005],ans[4];
void mn(char *T)
{
    int len=strlen(T),a,i;
    next[0]=len;
    a=1;
    for(i=0;i<len-1&&T[i]==T[i+1];i++);
        next[1]=i;
    for(int k=2;k<len;k++)
    {
        int p=a+next[a]-1,l=next[k-a];
        if((k-1)+l>=p)
        {
            int j=p-k+1>0?p-k+1:0;
            while(k+j<len&&T[j]==T[j+k])
                j++;
            next[k]=j;
            a=k;
        }
        else
            next[k]=l;
    }
}
void extend(char *S,char *T)
{
    int lens=strlen(S),lent=strlen(T),a;
    int ml=lens>lent?lent:lens;
    a=0;
    while(a<ml&&S[a]==T[a])
        a++;
    ext[0]=a;
    a=0;
    for(int k=1;k<lens;k++)
    {
        int p=a+ext[a]-1,l=next[k-a];
        if((k-1)+l>=p)
        {
            int j=p-k+1>0?p-k+1:0;
            while(k+j<lens&&j<lent&&T[j]==S[j+k])
                j++;
            ext[k]=j;
            a=k;
        }
        else
            ext[k]=l;
    }
}
int fail[200005];
int kmp(char* str) {
    int n = strlen(str);
    int p =fail[0] = -1;
    int j=0;
    while(j<n) {
        if(p==-1||str[p]==str[j])
        {
            p++;
            j++;
            fail[j]=p;
        }
        else
            p=fail[p] ;
    }
    return n - fail[n];
}
int main()
{
    char s[200005],t[200010];
    int t1,kcas=0;
    scanf("%d",&t1);
    while(t1--)
    {
        scanf("%s",s);
        int len=strlen(s);
        strcpy(t,s);
        strcat(t,s);
        int ss=kmp(t);
       // printf("%d\n",ss);
        memset(next,0,sizeof(next));
        mn(s);
        extend(t,s);
        int ans[3], tn = strlen(s);
        memset(ans, 0, sizeof(ans));
        for (int i = 0; i<ss; i++) {
            if (ext[i] >= tn)
                ans[1]++;
            else {
                int g = ext[i];
                if (s[g] < t[i+g])
                    ans[2]++;
                else
                    ans[0]++;
            }
        }
        printf("Case %d: %d %d %d\n", ++kcas, ans[0], ans[1], ans[2]);
       }    
       return 0;
}


 


 


 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值