HDU 트레이닝 기록1: KMP
전송문
제목: 작은 꿰미가 큰 꿰미에서 처음으로 일치하는 위치를 구합니다.
문제풀이: 간단한 문자열 일치, KMP 템플릿 문제입니다.
code:
#include<iostream>
#include<cstring>
#include<cstdio>
using namespace std;
const int max_n=1e6+5;
const int max_m=1e4+5;
int w[max_n],s[max_m];
int T[max_m];
int t,n,m,ans;
inline void calc_T(){
memset(T,0,sizeof(T));
T[0]=-1;
int j;
for (int i=0;i<m;++i){
j=T[i];
while (j!=-1&&s[i]!=s[j])
j=T[j];
T[i+1]=++j;
}
}
inline void calc_ans(){
ans=-1;
int j=0;
for (int i=0;i<n;++i){
while (j!=-1&&w[i]!=s[j])
j=T[j];
++j;
if (j==m){
ans=(i+1)-m+1;
return;
}
}
}
int main(){
scanf("%d",&t);
while (t--){
scanf("%d%d",&n,&m);
for (int i=0;i<n;++i) scanf("%d",&w[i]);
for (int i=0;i<m;++i) scanf("%d",&s[i]);
calc_T();
calc_ans();
printf("%d
",ans);
}
}
2、HDU 3336 Count the string
전송문
제목: 문자열의 모든 접두사가 문자열에 나타나는 횟수의 합을 구합니다.
문제풀이: 접두사는 뒤에 있는 문자의 어긋남에 나타난다. 사실은 모든 위치의 어긋남 개수의 합을 구하는 것이다.여기서 판단 조건은 짝짓기가 -1이 아니라는 것을 주의해야 한다. 짝짓기가 0이 되면 사실은 접두사 자체의 출현을 대표하기 때문이다.
code:
#include<iostream>
#include<cstring>
#include<cstdio>
using namespace std;
const int max_s=2e5+5;
const int Mod=10007;
char s[max_s];
int t,len,ans;
int T[max_s];
inline void calc_T(){
memset(T,0,sizeof(T));
T[0]=-1;
int j;
for (int i=0;i<len;++i){
j=T[i];
while (j!=-1&&s[i]!=s[j])
j=T[j];
T[i+1]=++j;
}
}
inline void calc_ans(){
ans=0;
int j;
for (int i=1;i<=len;++i){
j=T[i];
while (j!=-1)
j=T[j],ans=(ans+1)%Mod;
}
}
int main(){
scanf("%d",&t);
while (t--){
scanf("%d
",&len);
gets(s);
calc_T();
calc_ans();
printf("%d
",ans);
}
}
3、HDU 3746 Cyclic Nacklace
전송문
제목: 문자열을 최소한 두 번 순환하는 최소한의 추가 문자의 개수를 주십시오.
문제풀이: 최소 순환절 = 문자열 길이 - 끝자리가 어긋납니다.최소 순환절에 부족한 개수를 구하는 것이 답이다.
code:
#include<iostream>
#include<cstring>
#include<cstdio>
using namespace std;
const int max_s=1e5+5;
char s[max_s];
int t,len,ans;
int T[max_s];
inline void calc_T(){
T[0]=-1;
int j;
for (int i=0;i<len;++i){
j=T[i];
while (j!=-1&&s[i]!=s[j])
j=T[j];
T[i+1]=++j;
}
}
inline void calc_ans(){
if (len%(len-T[len])==0&&len!=len-T[len]) ans=0;
else ans=len-T[len]-(len%(len-T[len]));
}
int main(){
scanf("%d
",&t);
while (t--){
gets(s);
len=strlen(s);
calc_T();
calc_ans();
printf("%d
",ans);
}
}
4、HDU 1538 Period
전송문
제목: 한 사람당 1보다 큰 최대 순환 횟수를 구합니다.
문제풀이: 아니면 위의 결론을 이용하여: 최소 순환절 = 길이-말위 어긋남.한 분 한 분 일일이 열거하면 된다.
code:
#include<iostream>
#include<cstring>
#include<cstdio>
using namespace std;
const int max_n=1e6+5;
int n,num;
char s[max_n];
int T[max_n];
inline void calc_T(){
T[0]=-1;
int j;
for (int i=0;i<n;++i){
j=T[i];
while (j!=-1&&s[i]!=s[j])
j=T[j];
T[i+1]=++j;
}
}
int main(){
while (~scanf("%d
",&n)){
if (!n) return 0;
memset(T,0,sizeof(T));
printf("Test case #%d
",++num);
gets(s);
calc_T();
for (int i=2;i<=n;++i){
if (i%(i-T[i])==0&&i!=i-T[i])
printf("%d %d
",i,i/(i-T[i]));
}
putchar('
');
}
}
5, HDU 2087 클립
전송문 얻기 힘든 중국어 문제...
제목: 작은 꿰미가 큰 꿰미 중 가장 많은 일치 횟수를 반복하지 않도록 하십시오.
문제풀이: KMP 클래식 모형으로 매번 찾은 후 어긋나지 않고 0으로 뛰면 됩니다.
code:
#include<iostream>
#include<cstring>
#include<cstdio>
using namespace std;
const int max_s=1005;
char W[max_s],s[max_s];
int T[max_s];
int len_s,len_W,ans;
inline void calc_T(){
memset(T,0,sizeof(T));
T[0]=-1;
int j;
for (int i=0;i<len_s;++i){
j=T[i];
while (j!=-1&&s[i]!=s[j])
j=T[j];
T[i+1]=++j;
}
}
inline void calc_ans(){
int j=0;
ans=0;
for (int i=0;i<len_W;++i){
while (j!=-1&&W[i]!=s[j])
j=T[j];
++j;
if (j==len_s){
ans++;
j=0;
}
}
}
int main(){
while (~scanf("%s",W)){
if (W[0]=='#') return 0;
scanf("%s",s);
len_s=strlen(s);
len_W=strlen(W);
calc_T();
calc_ans();
printf("%d
",ans);
}
}
6、HDU 2594 Simpsons’Hidden Talents
전송문
제목: 가장 긴 공통 접두사를 구하십시오.
문제풀이: 두 개의 열을 연결한 다음에 어긋난 함수를 구하면 된다.마지막 비트와 두 문자열의 길이의 관계를 잘 판단하십시오.
code:
#include<iostream>
#include<cstring>
#include<cstdio>
using namespace std;
const int max_s=5e5+5;
char s[max_s],s2[max_s];
int T[max_s];
int l1,l2,len,ans;
inline void calc_T(){
memset(T,0,sizeof(T));
T[0]=-1;
int j;
for (int i=0;i<len;++i){
j=T[i];
while (j!=-1&&s[i]!=s[j])
j=T[j];
T[i+1]=++j;
}
}
inline void calc_ans(){
if (T[len]<=min(l1,l2)) ans=T[len];
else ans=min(l1,l2);
}
int main(){
while (~scanf("%s %s",s,s2)){
l1=strlen(s);
l2=strlen(s2);
for (int i=0;i<l2;++i)
s[l1+i]=s2[i];
len=l1+l2;
calc_T();
calc_ans();
for (int i=0;i<ans;++i)
putchar(s[i]);
if (ans) putchar(' ');
printf("%d
",ans);
}
}
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
알고리즘 - Knuth, Morris, Prett흔히 찾는 문자나 문자열이 있는 지 없는 지를 확인할 때는 주로 if pattern in words 이런 식으로 검사를 할 수 있다. pi 테이블은 찾으려는 문자열(pattern)의 정보를 저장하고 있는 배열, 자료...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.