两道题都是求循环节的。。。但是一道是学哈希时做的,另一道是学$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[1<<15],*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=0,fix=1; register char ch; while(!isdigit(ch=getchar())) fix=ch=='-'?-1:fix; do ret=ret*10+(ch^48); while(isdigit(ch=getchar())); return ret*fix; } }using Fread::g; const int B=131,N=1000010; ll f[N],p[N]; inline ll calc(int l,int r) {return f[r]-f[l-1]*p[r-l+1];} signed main() { #ifdef JACK freopen("NOIPAK++.in","r",stdin); #endif p[0]=1; for(R i=1;i<=N-10;++i) p[i]=p[i-1]*B; while(1) { register char s[N]; scanf("%s",s+1); R n=strlen(s+1); if(n==1&&s[1]=='.') break; for(R i=1;i<=n;++i) f[i]=f[i-1]*B+s[i]-96; for(R i=1;i<=n;++i) if(n%i==0) { register ll tmp=calc(1,i); register bool flg=false; for(R l=i+1;l<=n;l+=i) { if(tmp!=calc(l,l+i-1)) {flg=1; 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[1<<15],*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=0,fix=1; register char ch; while(!isdigit(ch=getchar())) fix=ch=='-'?-1:fix; do ret=ret*10+(ch^48); while(isdigit(ch=getchar())); return ret*fix; } inline bool isempty(const char& ch) {return ch<=36||ch>=127;} 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=1000010; char s[N]; int nxt[N],n,t; inline void PRE() { nxt[1]=0; for(R i=2,j=0;i<=n;++i) { while(j&&s[i]!=s[j+1]) j=nxt[j]; if(s[i]==s[j+1]) ++j; nxt[i]=j; } } signed main() { #ifdef JACK freopen("NOIPAK++.in","r",stdin); #endif while(n=g(),n>0) { gs(s+1); PRE(); printf("Test case #%d\n",++t); for(R i=2;i<=n;++i) { if(i%(i-nxt[i])==0&&i/(i-nxt[i])>1) printf("%d %d\n",i,i/(i-nxt[i])); } printf("\n"); } }
2019.06.27