poj KMP题目总汇

http://www.cnblogs.com/wuyiqi/archive/2012/01/06/2314078.html

poj 2406  简单求周期

View Code
#include<cstdio>
#include<cstring>
char b[1000010];
int p[1000010];
int m,n;
void getp(){
p[1]=0;
int i,j=0;
for(i=2;i<=m;i++){
while(j>0&&b[j+1]!=b[i]) j=p[j];
if(b[j+1]==b[i]) j+=1;
p[i]=j;
}
}
int main(){
while(scanf("%s",b+1)!=EOF)
{
if(b[1]=='.') break;
m=strlen(b+1);
getp();
if(m%(m-p[m])==0) printf("%d\n",m/(m-p[m]));
else printf("1\n");
}
}


poj 2752 Seek the Name, Seek the Fame

求既是前缀又是后缀的前缀的可能的长度

还是利用next的特性,一直next下去,把答案逆序输出即可

View Code
#include<cstdio>
#include<cstring>
char b[1000010];
int p[1000010];
int m,n;
void getp(){
p[1]=0;
int i,j=0;
for(i=2;i<=m;i++){
while(j>0&&b[j+1]!=b[i]) j=p[j];
if(b[j+1]==b[i]) j+=1;
p[i]=j;
}
}
int tot=0;
int ans[1000010];
int main(){
while(scanf("%s",b+1)!=EOF)
{
tot=0;
m=strlen(b+1);
getp();
int tmp=p[m];
if(tmp!=0) ans[tot++]=tmp;
while(p[tmp]>0)
{
tmp=p[tmp];
ans[tot++]=tmp;
}
for(int i=tot-1;i>=0;i--)
printf("%d ",ans[i]);
printf("%d\n",m);
}
}

 

poj 3461   Oulipo

简单题,直接模板

View Code
#include<cstdio>
#include<cstring>
int n,m;
char a[1000010],b[10010];
int p[11111];
void getp(){
p[1]=0;
int i,j=0;
for(i=2;i<=m;i++){
while(j>0&&b[j+1]!=b[i]) j=p[j];
if(b[j+1]==b[i]) j+=1;
p[i]=j;
}
}
int kmp()
{
int i,j=0,cnt=0;
for(i=1;i<=n;i++){
while(j>0&&b[j+1]!=a[i]) j=p[j];
if(b[j+1]==a[i]) j+=1;
if(j==m){
cnt++;
j=p[j];

}
}
return cnt;
}
int main()
{
int t;
scanf("%d",&t);
while(t--)
{
scanf("%s%s",b+1,a+1);
m=strlen(b+1);
n=strlen(a+1);
getp();
printf("%d\n",kmp());
}
}


poj 2185 

来自:

http://blog.sina.com.cn/s/blog_69c3f0410100tyjl.html

比较新颖的是把一整行的字符当做一个字符,r行字符相当于一个字符串,求最小的循环节

abc

bcd

def

abc

循环节为3,很巧妙而又灵活地利用了next【】的意义,也节省了代码量

debug了好长时间

最后发现,1 1 a 输出了2.。。。

View Code
#include<cstdio>
#include<cstring>
char s[10010][80];
int p[10010];
int flag[80];
char tmp[80];
int main()
{
int x,y,r,c,i,j;
while(scanf("%d%d",&r,&c)!=EOF){
memset(flag,0,sizeof(flag));
for(i=1;i<=r;i++){
scanf("%s",s[i]+1);
strcpy(tmp+1,s[i]+1);
for(j=c-1;j>0;j--){
tmp[j+1]=0;
for(x=1,y=1;s[i][y];x++,y++){
if(!tmp[x]) x=1;
if(tmp[x]!=s[i][y]) break;
}
if(!s[i][y]) flag[j]++;
}
}
for(j=0;j<c;j++)
if(flag[j]==r) break;
x=j;
for(i=1;i<=r;i++) s[i][x+1]=0;
p[1]=0;
for(i=2,j=0;i<=r;i++)
{
while(j>0&&strcmp(s[j+1]+1,s[i]+1)) j=p[j];
if(!strcmp(s[j+1]+1,s[i]+1)) j+=1;
p[i]=j;
}
printf("%d\n",x*(r-p[r]));
}
}


poj  3080  Blue Jeans

题意:求最长的公共子串,要注意的是字典序最小

枚举子串+kmp匹配,判断某个子串是否存在与每个字符串中

View Code
#include<cstdio>
#include<cstring>
char str[20][70];
char tmp[70];
int p[70];
void getp(int m,char *b1){
char b[70];
strcpy(b+1,b1);
p[1]=0;
int i,j=0;
for(i=2;i<=m;i++){
while(j>0&&b[j+1]!=b[i]) j=p[j];
if(b[j+1]==b[i]) j+=1;
p[i]=j;
}
}
bool kmp(char *a1,char *b1,int n,int m)
{
char a[70],b[70];
strcpy(a+1,a1);strcpy(b+1,b1);
int i,j=0,cnt=0;
for(i=1;i<=n;i++){
while(j>0&&b[j+1]!=a[i]) j=p[j];
if(b[j+1]==a[i]) j+=1;
if(j==m){
return true;
}
}
return false;
}
bool check(char *s,int tot)
{
int i,j;
for(i=2;i<=tot;i++)
{
int n=strlen(str[i]+1),m=strlen(s);
if(!kmp(str[i]+1,s,n,m))
return false;
}
return true;
}
char ans[70];
int main()
{
int t,n,i,j;
scanf("%d",&t);
while(t--)
{
scanf("%d",&n);
for(i=1;i<=n;i++) scanf("%s",str[i]+1);
int len=strlen(str[1]+1);
int L=0;
for(i=1;i<=len;i++)
{
for(j=1;j<=len-i+1;j++)
{
strncpy(tmp,str[1]+j,i);
memset(p,0,sizeof(p));
getp(i,tmp);
if(check(tmp,n))
{
if(i>=L)
{
if(strcmp(tmp,ans)<0&&i==L) strcpy(ans,tmp);
if(i>L) strcpy(ans,tmp);
L=strlen(ans);
}
}
memset(tmp,0,sizeof(tmp));
}
}
if(L>=3) puts(ans);
else puts("no significant commonalities");
}
}

 

 

poj 3450 ,同上,没有二分,直接暴力也过了,囧。。。

 

 



posted @ 2012-01-06 21:45  Because Of You  Views(8189)  Comments(0Edit  收藏  举报