Revolving Digits HDU - 4333

http://acm.hdu.edu.cn/showproblem.php?pid=4333

t是原串 s是两个t拼在一起 exkmp求出s的每个后缀和t的公共前缀长度即可 因为要去掉所有同构串 所以还要跑kmp求出循环节长度

#include <bits/stdc++.h>
using namespace std;
const int maxn=1e5+10;

int nxtt[2*maxn],nxts[2*maxn];
int l;
char t[maxn],s[2*maxn];

void kmp(char *t,int lt)
{
    int i,j;
    nxtt[0]=-1;
    i=0,j=-1;
    while(i<lt)
    {
        if(j==-1||t[i]==t[j])
        {
            i++,j++;
            nxtt[i]=j;
        }
        else j=nxtt[j];
    }
}

void exkmp(char *t,int lt)
{
    int i=0,j,po;
    nxtt[0]=lt;//初始化next[0]
    while(t[i]==t[i+1]&&i+1<lt)//计算next[1]
    i++;
    nxtt[1]=i;
    po=1;//初始化po的位置
    for(i=2;i<lt;i++)
    {
        if(nxtt[i-po]+i<nxtt[po]+po)//第一种情况,可以直接得到next[i]的值
        nxtt[i]=nxtt[i-po];
        else//第二种情况,要继续匹配才能得到next[i]的值
        {
            j=nxtt[po]+po-i;
            if(j<0)j=0;//如果i>po+next[po],则要从头开始匹配
            while(i+j<lt&&t[j]==t[j+i])//计算next[i]
            j++;
            nxtt[i]=j;
            po=i;//更新po的位置
        }
    }
}

void solve(char *s,int ls,char *t,int lt)
{
    int i=0,j,po;
    while(s[i]==t[i]&&i<lt&&i<ls)//计算ex[0]
    i++;
    nxts[0]=i;
    po=0;//初始化po的位置
    for(i=1;i<ls;i++)
    {
        if(nxtt[i-po]+i<nxts[po]+po)//第一种情况,直接可以得到ex[i]的值
        nxts[i]=nxtt[i-po];
        else//第二种情况,要继续匹配才能得到ex[i]的值
        {
            j=nxts[po]+po-i;
            if(j<0)j=0;//如果i>ex[po]+po则要从头开始匹配
            while(i+j<ls&&j<lt&&s[j+i]==t[j])//计算ex[i]
            j++;
            nxts[i]=j;
            po=i;//更新po的位置
        }
    }
}

int main()
{
    int tt,cas,i,ans1,ans2,ans3,div;
    scanf("%d",&tt);
    for(cas=1;cas<=tt;cas++)
    {
        scanf("%s",t);
        l=strlen(t);
        for(i=0;i<l;i++) s[i]=s[i+l]=t[i];
        exkmp(t,l);
        solve(s,2*l,t,l);
        ans1=ans2=ans3=0;
        for(i=0;i<l;i++)
        {
            if(nxts[i]==l) ans2++;
            else
            {
                if(s[i+nxts[i]]<s[nxts[i]]) ans1++;
                else ans3++;
            }
        }
        kmp(t,l);
        if(l!=nxtt[l]&&l%(l-nxtt[l])==0) div=l/(l-nxtt[l]);
        else div=1;
        printf("Case %d: %d %d %d\n",cas,ans1/div,ans2/div,ans3/div);
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/sunyutian1998/article/details/82980654
今日推荐