hdu 4333 Revolving Digits 夜

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

对我来说这个题 太难了  看着标准程序敲的  伤不起呀

解析说是和KMP有关 不过已经变形的不成样子了 如果在比赛时做出了  你真的是牛神了

基本方法就是 先copy一个放在原串后面

依次求 以某处为开始点比较时原串要比较到的位置 位置超出字符串长度 说明相等

还要出来连续循环的情况 因为要找不同的数

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<ctime>
#include<queue>
#include<cstring>
#include<set>
#include<cmath>
#include<algorithm>
#define LL long long
using namespace std;
const int N=200005;
char s[N];
int next[N];//next 指向的是以此点开始的字符串应该与原串中的哪个字符进行比较
// 当然比较的时候此串也要找对应的字符进行比较 如果超过字符串长度 说明相等
void getnext(int n)
{
    int l=1,r=-1;//l 和 r 代表循环串的左右位置
    next[0]=0;
    for(int i=1;i<n;++i)
    {
        if(i+next[i-l]<=r)
        {
            next[i]=next[i-l];//如果前面对应的循环串对应位置字符要找的位置对应到本串中字符要找的位置没有超过r  说明可以直接将答案copy过来
        }else
        {
            int j=max(r-i+1,0);//否则选择可以最靠后开始的位置进行依次比较 直到找到不同的 并记录循环串位置
            for(;j+i<2*n;++j)
            if(s[j]!=s[i+j])
            break;
            next[i]=j;
            l=i;
            r=i+j-1;
        }
    }
}
int main()
{
   int T;
   //freopen("data.txt","r",stdin);
   scanf("%d",&T);
   getchar();
   for(int c=1;c<=T;++c)
   {
        gets(s);
        int n=strlen(s);
        for(int i=0;i<n;++i)
        {
            s[i+n]=s[i];
        }
        s[n*2]=0;//copy2
        getnext(n);
        int i;
        for(i=1;i<n;++i)
        if(i+next[i]>=n)
        break;//找连续循环串位置  
        int m=(n%i)?m:i;?//如果可以除进  则只要环内部分
        int l=0,q=1,g=0;
        for(i=1;i<m;++i)
        {
            if(next[i]>=n)
            {
                ++q;
            }
            else if(s[next[i]]>s[i+next[i]])
            {
                ++l;
            }else
            {
                ++g;
            }
        }
        printf("Case %d: %d %d %d\n",c,l,q,g);
   }
   return 0;
}
原文地址:https://www.cnblogs.com/liulangye/p/2622761.html