计蒜客 旋转数字 (kmp+exkmp)

 首先得去重,怎么去重呢,刚开始想了好几种方法,都不太理想,后再才想明白,找重复的不就是找找循环节嘛,因为如果存在循环节,那么一定会造成重复,比如123123123,循环节是3,所以只需要循环数字三次即可,再多循环就会造成重复,那么问题就来了,怎么计算循环节呢?在学习kmp中,我们利用fail数组的功能,很容易计算得到循环节。证明我这就不了,只说下方法,就是s.size()-fail[s.size()],当然这得要s.size()能整除前面那个式子才能是循环节。找到循环节了,又该怎么办呢,该怎么比较呢,不妨先列下来看看:

假设该数为:21213,那么下面就是他的悬转数字。

32121

13212

21321

12132

21213

正着看不好看,那么就倒着看,咦~,这不就是扩展kmp嘛。前后缀进行比较啦。从前后缀初出现不相等的第一个元素开始比较。

好啦,现在开始写程序啦。

 

#include<cstdio>
#include<cstring>
#include<algorithm>

using namespace std;

const int maxn=1e5+10;

int Next[maxn];
int extand[maxn];       //s的后缀与t的最长公共前缀。
int fail[maxn];

void get_fail(char *pattern)
{
    int k=-1;
    fail[0]=-1;
    int len=strlen(pattern);
    for(int i=1;i<len;i++)
    {
        while(k>-1&&pattern[k+1]!=pattern[i]) k=fail[k];
        if(pattern[k+1]==pattern[i])
            k++;
        fail[i]=k;
    }
}

void getnext(char* t)
{
    int i,len=strlen(t);
    Next[0]=len;
    for(i=0;i<len-1&&t[i]==t[i+1];i++);
    Next[1]=i;
    int a=1;
    for(int k=2;k<len;k++){
        int p=a+Next[a]-1,l=Next[k-a];
        if(k+l-1>=p){       //l>=p-k+1
            int j=max(p-k+1,0);
            while(k+j<len&&t[k+j]==t[j]) j++;
            Next[k]=j;a=k;
        }else Next[k]=l;
    }
}

int main()
{
    char s[maxn],t[maxn];
    while(scanf("%s",s)!=EOF){
        getnext(s);
        get_fail(s);
        int len=strlen(s);
        int tmp=len-fail[len-1]-1;
        int flag;
        if(len%tmp==0) flag=tmp;
        else flag=len;
        int same=0,da=0,xiao=0;
        for(int i=0;i<flag;i++){
            if(Next[i]==len) same++;
            else if(s[Next[i]+i]>s[Next[i]]) da++;
            else if(s[Next[i]+i]<s[Next[i]]) xiao++;
        }
        printf("%d %d %d\n",xiao,same,da);
    }
    return 0;
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值