專題訓練ING
今天弄了一天的 KMP ,大且做個總結(poj kmp)。
poj 3167 .3080(另開博文)2752.1961.2406
1961.2406
求一個串能否被其一子串完全不重複覆寫
利用next數組的性質,自我比對一遍即可,判斷i是否整除i-next[i]
1961
#include<cstdio>
#include<cstdlib>
#include<algorithm>
#include<cmath>
#include<cstring>
using namespace std;
char s[1000011];
int next[1000011];
int n,i,t,j,x;
char c;
void Read()
{
while(c=getchar(),c<'a'||c>'z');
s[++n]=c;
while(c=getchar(),c>='a'&&c<='z')s[++n]=c;
}
int main()
{
while(true){
scanf("%d",&n);
t++;
if(n==0)break;
n=0;
Read();
x=0;
for(i=2;i<=n;i++){
while(x!=0&&s[i]!=s[x+1])x=next[x];
if(s[i]==s[x+1])x++;
next[i]=x;
}
printf("Test case #%d
",t);
for(i=2;i<=n;i++){
if(i%(i-next[i])==0&&i/(i-next[i])!=1)printf("%d %d
",i,i/(i-next[i]));
}
printf("
");
}
}
2406
#include<cstdio>
#include<cstdlib>
#include<algorithm>
#include<cmath>
#include<cstring>
using namespace std;
char s[1000011];
int next[1000011];
bool p;
int n,i,j,x;
char c;
void Read()
{
while(c=getchar(),c!='.'&&(c<'a'||c>'z'));
if(c=='.')p=false;
s[++n]=c;
while(c=getchar(),c>='a'&&c<='z')s[++n]=c;
}
int main()
{
while(true){
p=true;
n=0;
Read();
if(p==false)break;
memset(next,0,sizeof(next));
x=0;
for(i=2;i<=n;i++){
while(x!=0&&s[i]!=s[x+1])x=next[x];
if(s[i]==s[x+1])x++;
next[i]=x;
}
if(n%(n-next[n])!=0)printf("1
");
else printf("%d
",n/(n-next[n]));
}
}
2752
不斷next..
#include<cstdio>
#include<cstdlib>
#include<algorithm>
#include<cmath>
#include<cstring>
using namespace std;
char s1[400011],s[400011];
int next[400011];
int n,i,j,x,t;
int ans[400011];
int main()
{
while(scanf("%s",&s)!=EOF){
n=strlen(s);
for(i=1;i<=n;i++)s1[i]=s[i-1];
x=0;
for(i=2;i<=n;i++){
while(x!=0&&s1[i]!=s1[x+1])x=next[x];
if(s1[i]==s1[x+1])x++;
next[i]=x;
}
t=0;
x=n;
while(x!=0){
ans[++t]=x;
x=next[x];
}
for(i=t;i>=2;i--)printf("%d ",ans[i]);
printf("%d
",ans[1]);
}
}