两道题都是求循环节的。。。但是一道是学哈希时做的,另一道是学$KMP$时做的


POJ2604 用的哈希。。。枚举长度的因数作为循环节的长度,然后暴力算出所有循环节位置的哈希值,看看是否相等。

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<cctype>
#include<cstdlib>
#include<vector>
#include<queue>
#include<map>
#include<set>
#define ll unsigned long long
#define R register int
using namespace std;
namespace Fread {
static char B[<<],*S=B,*D=B;
#define getchar() (S==D&&(D=(S=B)+fread(B,1,1<<15,stdin),S==D)?EOF:*S++)
inline int g() {
R ret=,fix=; register char ch; while(!isdigit(ch=getchar())) fix=ch=='-'?-:fix;
do ret=ret*+(ch^); while(isdigit(ch=getchar())); return ret*fix;
}
}using Fread::g;
const int B=,N=;
ll f[N],p[N];
inline ll calc(int l,int r) {return f[r]-f[l-]*p[r-l+];}
signed main() {
#ifdef JACK
freopen("NOIPAK++.in","r",stdin);
#endif
p[]=; for(R i=;i<=N-;++i) p[i]=p[i-]*B;
while() { register char s[N];
scanf("%s",s+); R n=strlen(s+);
if(n==&&s[]=='.') break;
for(R i=;i<=n;++i) f[i]=f[i-]*B+s[i]-;
for(R i=;i<=n;++i) if(n%i==) { register ll tmp=calc(,i);
register bool flg=false;
for(R l=i+;l<=n;l+=i) {
if(tmp!=calc(l,l+i-)) {flg=; break;}
} if(!flg) {printf("%d\n",n/i);break;}
}
}
}

POJ1961 用的$kmp$详解

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<cctype>
#include<cstdlib>
#include<vector>
#include<queue>
#include<map>
#include<set>
#define ull unsigned long long
#define ll long long
#define R register int
using namespace std;
namespace Fread {
static char B[<<],*S=B,*D=B;
#define getchar() (S==D&&(D=(S=B)+fread(B,1,1<<15,stdin),S==D)?EOF:*S++)
inline int g() {
R ret=,fix=; register char ch; while(!isdigit(ch=getchar())) fix=ch=='-'?-:fix;
do ret=ret*+(ch^); while(isdigit(ch=getchar())); return ret*fix;
} inline bool isempty(const char& ch) {return ch<=||ch>=;}
inline void gs(char* s) {register char ch; while(isempty(ch=getchar())); do *s++=ch; while(!isempty(ch=getchar()));}
}using Fread::g; using Fread::gs;
const int N=;
char s[N]; int nxt[N],n,t;
inline void PRE() { nxt[]=;
for(R i=,j=;i<=n;++i) {
while(j&&s[i]!=s[j+]) j=nxt[j];
if(s[i]==s[j+]) ++j; nxt[i]=j;
}
}
signed main() {
#ifdef JACK
freopen("NOIPAK++.in","r",stdin);
#endif
while(n=g(),n>) {
gs(s+); PRE(); printf("Test case #%d\n",++t);
for(R i=;i<=n;++i) {
if(i%(i-nxt[i])==&&i/(i-nxt[i])>)
printf("%d %d\n",i,i/(i-nxt[i]));
} printf("\n");
}
}

2019.06.27

05-27 18:45