hdu - 4333 - Revolving Digits - 확장 kmp
http://acm.hdu.edu.cn/showproblem.php?pid=4333
void build_next()
{
int k, q, p, a;
next[0] = len_t;
for (k = 1, q = -1; k < len_t; k ++, q –)
{
if (q < 0 || k + next[k - a] >= p)
{
if (q < 0)q = 0, p = k;
//q B ,p A , +1
//q 1, B
while (p < len_t && T[p] == T[q])
{
p ++, q ++;
}
next[k] = q, a = k;
}
else
{
next[k] = next[k - a];
}
}
}
void extend_KMP()
{
int k, q, p, a;
for (k = 0, q = -1; k < len_s; k ++, q –)
{
if (q < 0 || k + next[k - a] >= p)
{
if (q < 0)q = 0, p = k;
while (p < len_s && q < len_t && S[p] == T[q])
{
p ++, q ++;
}
extend[k] = q, a = k;
}
else
{
extend[k] = next[k - a];
}
}
}
문제 풀이:
이 문제 의 중점 은 x 가 디지털 교대 후의 모든 수 와 x 의 크기 관 계 를 비교 하 는 것 이다.x 가 매우 크기 때문에 우 리 는 x 와 교대 후의 모든 수 를 x 길이 의 문자열 로 보고 문자열 을 비교 해 야 한다.즉, 우 리 는 x 뒤에 x 를 연결 하여 xx 로 바 꾼 다음 에 xx 앞 n 위 가 모든 시작 길이 가 n 인 문자열 과 xx 앞 n 위의 크기 를 비교 할 수 있다.만약 에 우리 가 xx 의 모든 사람과 xx 의 가장 긴 공공 접두사 의 길 이 를 빨리 구 할 수 있다 면 크기 를 비교 할 수 있다 면 우 리 는 O (1) 의 시간 만 필요 하고 모든 사람의 가장 긴 공공 접 두 사 를 구 할 수 있다. 확장 KMP 알고리즘 을 사용 하여 O (n) 시간 안에 구 할 수 있다. 그러면 O (n) 시간 안에 모든 비 교 를 완성 할 수 있다.
비교 하 는 것 을 제외 하고 본 문 제 는 숫자 에 대해 심 도 를 해 야 한다. 관찰 을 통 해 우 리 는 반복 되 는 숫자 가 나타 나 는 상황 은 원래 의 x 에 순환 절 이 존재 한 다 는 것 을 설명 한다. 우 리 는 x 의 최소 순환 절 을 찾 은 다음 에 순환 절 안의 숫자 만 비교 하면 된다.그리고 최소 순환 절 을 구 하 는 것 도 KMP 알고리즘 이나 KMP 알고리즘 을 확장 하여 얻 을 수 있 습 니 다. 그러면 전체 시간 복잡 도 는 O (n) 입 니 다.
#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)
{//next[i] s s[i..n]
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
",c,l,q,g);
}
return 0;
}
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
다양한 언어의 JSONJSON은 Javascript 표기법을 사용하여 데이터 구조를 레이아웃하는 데이터 형식입니다. 그러나 Javascript가 코드에서 이러한 구조를 나타낼 수 있는 유일한 언어는 아닙니다. 저는 일반적으로 '객체'{}...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.