题意:一个数字,依次将第一位放到最后一位,问小于本身的数的个数及等于本身的个数和大于本身的个数,但是要注意重复的不再计算
思路:用扩展KMP我们可以处理,先将串复制到后面一次,然后求扩展KMP,那么我们如何比较呢,如果extand[i]的值大于串的长度len,说明我以i为开头的串和原串的匹配大于len,也就说明这个串和原串相等,接下来就是另外两种情况,若extand[i]匹配到了第三位,那么久比较原串的第三位和以i开始的第三位即可,比较过后,处理重复的串,用KMP即可处理,如果串是一个以长度为len1的子串重复得来,那么最后结果便全部除以len1,画一下就一目了然了
#include <stdio.h> #include <stdlib.h> #include <string.h> #include <iostream> #include <algorithm> using namespace std; const int maxn=200010; int Next[maxn],extand[maxn]; char T[maxn]; void makenext(int m){ int i=0,j=-1; Next[i]=-1; while(i<m){ if(j==-1||T[i]==T[j]) Next[++i]=++j; else j=Next[j]; } } void GetNext(const char *T){ int len=strlen(T),a=0; extand[0]=len; while(a<len-1&&T[a]==T[a+1]) a++; extand[1]=a; a=1; for(int k=2;k<len;k++){ int p=a+extand[a]-1,L=extand[k-a]; if((k-1)+L>=p){ int j=(p-k+1)>0? (p-k+1):0; while(k+j<len&&T[k+j]==T[j]) j++; extand[k]=j; a=k; } else extand[k]=L; } } int main(){ int TT,t=1; scanf("%d",&TT); while(TT--){ scanf("%s",T); int len=strlen(T); makenext(len); int k=len-Next[len]; int tt; if(len%k==0) tt=len/k; else tt=1; for(int i=0;i<len;i++) T[len+i]=T[i]; GetNext(T); int L=0,E=0,G=0; for(int i=0;i<len;i++){ if(extand[i]>=len) E++; else if(T[extand[i]]>T[i+extand[i]]) L++; else if(T[extand[i]]<T[i+extand[i]]) G++; } printf("Case %d: %d %d %d\n",t++,L/tt,E/tt,G/tt); } return 0; }
时间: 2024-10-29 10:45:46