首页 > 其他 > 详细

hdu poj KMP简单题目总结

时间:2014-02-07 09:40:19      阅读:411      评论:0      收藏:0      [点我收藏+]

hdu 3336

 题意:输入一个字符串求每个前缀在串中出现的次数和

sol:只要稍微理解下next 数组的含义就知道只要把每个有意义的next值得个数加起来即可

PS:网上有dp解法orz,dp[i]表示以i为前缀串结尾的前缀串的总和,方程很容易写出

bubuko.com,布布扣
//字符串上KMP(水)
//从前向后扫,失配函数的位置就是一个前缀的位置减1
//加起来就好了
// by acvc
#include<cstring>
#include<cstdio>
#include<algorithm>
using namespace std;
const int MAX = 200000;
const int MOD = 10007;
char str[MAX];
int next[MAX],vis[MAX];
int main()
{
    int cas,n;
    scanf("%d",&cas);
    while(cas--)
    {
        scanf("%d %s",&n,str);
        next[0]=next[1]=0;
        for(int i=1;i<n;i++)
        {
            int j=next[i];
            while(j&&str[i]!=str[j]) j=next[j];
            if(str[i]==str[j])
            next[i+1]=j+1;
            else next[i+1]=0;
        }
        int ans=0,cnt=0;
        for(int i=0;i<n;i++)
        {
            if(next[i])
            {
            //    cnt++;
                ans=(ans+2)%MOD;
            }
            else
            ans=(ans+1)%MOD;
        }
        if(next[n]) ans=(ans+1)%MOD;
        printf("%d\n",(ans)%MOD);
    }
    return 0;
bubuko.com,布布扣

} 

 hdu 1358

题意:给出一个字符串求出每个前缀的最小周期

sol:next数组理解题目稍微想想就知道t=(len-next[len])

bubuko.com,布布扣
//kmp小深入题目
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int MAX = 10000000+10;
char str[MAX]; int next[MAX]; //失配函数
int main()
{
    int n,cnt=0;
    while(scanf("%d",&n)>0)
    {
        scanf("%s",str);
        next[0]=next[1]=0;
        for(int i=1;i<n;i++)
        {
            int j=next[i];
            while(j&&str[i]!=str[j]) j=next[j];
            if(str[i]==str[j]) next[i]=j+1;
            else next[i]=0;
        }
        printf("Test case #%d\n",++cnt);
        for(int i=2;i<=n;i++)
        {
            if(next[i]&&i%(i-next[i])==0)
            printf("%d %d\n",i,i%(i-next[i]));
        }
    }
    return 0;
bubuko.com,布布扣

} 

 hdu1711

题意:给出两个数组,求出b在a中最先匹配的位置

sol:KMP裸题

bubuko.com,布布扣
 1 //裸题
 2 #include<cstring>
 3 #include<cstdio>
 4 #include<algorithm>
 5 using namespace std;
 6 const int MAX = 1e6+10;
 7 int next[MAX];
 8 int a[MAX],b[MAX];
 9 int main()
10 {
11     int cas,n,m;
12     scanf("%d",&cas);
13     while(cas--)
14     {
15         scanf("%d %d",&n,&m);
16         for(int i=0;i<n;i++) scanf("%d",&a[i]);
17         for(int j=0;j<m;j++) scanf("%d",&b[j]);
18         next[1]=next[0]=0;
19         for(int i=1;i<m;i++)
20         {
21             int j=next[i];
22             while(j&&b[i]!=b[j]) j=next[j];
23             if(b[i]==b[j]) next[i+1]=j+1;
24             else next[i+1]=0;
25         }
26         int cur=0,flag=0;
27         for(int i=0;i<n;i++)
28         {
29             while(cur&&a[i]!=b[cur]) cur=next[cur];
30             if(a[i]==b[cur]) cur++;
31             if(cur==m)
32             {
33                 flag=1;
34                 printf("%d\n",i-cur+2);
35                 break;
36             }
37         }
38         if(!flag) printf("-1\n");
39     }
40     return 0;
bubuko.com,布布扣

41 }

 

hdu2087

题意:给定串1和串2求串2在串1中出现的顺序

sol;裸KMP从前向后扫一遍kmp就好了

bubuko.com,布布扣
 1 #include<cstring>
 2 #include<algorithm>
 3 #include<cstdio>
 4 using namespace std;
 5 const int MAX = 1000+10;
 6 char str1[MAX],str2[MAX];
 7 int next[MAX];
 8 int main()
 9 {
10     while(scanf("%s",str1)&&strcmp(str1,"#"))
11     {
12         int ans=0;
13         scanf("%s",str2);
14         int n=strlen(str2); next[0]=next[1]=0;
15         for(int i=1;i<n;i++)
16         {
17             int j=next[i];
18             while(j&&str2[i]!=str2[j]) j=next[j];
19             if(str2[i]==str2[j]) next[i+1]=j+1;
20             else next[i+1]=0;
21         }
22         int len=strlen(str1); int j=0;
23         for(int i=0;i<len;i++)
24         {
25             while(j&&str1[i]!=str2[j]) j=next[j];
26             if(str1[i]==str2[j]) j++;
27             if(j==n)
28             {
29                 ans++;
30                 j=0;
31             }
32         }
33         printf("%d\n",ans);
34     }
35     return 0;
bubuko.com,布布扣

36 }

 

 poj2406

题意:给定一个串求出串的最小周期

los:失配函数裸题啊

bubuko.com,布布扣
 1 //kmp-shui
 2 #include<cstring>
 3 #include<algorithm>
 4 #include<cstdio>
 5 using namespace std;
 6 const int MAX = 1e6+10;
 7 char str[MAX]; int next[MAX];
 8 int main()
 9 {
10     int ans;
11     while(1)
12     {
13         gets(str); if(!strcmp(str,".")) break;
14         int n=strlen(str); next[0]=next[1]=0;
15         for(int i=1;i<n;i++)
16         {
17             int j=next[i];
18             while(j&&str[i]!=str[j]) j=next[j];
19             if(str[i]==str[j]) next[i+1]=j+1;
20             else next[i+1]=0;
21         }
22         if(n%(n-next[n])==0)
23         printf("%d\n",n/(n-next[n]));
24         else printf("1\n");
25     }
26     return 0;
bubuko.com,布布扣

27 }

 

poj 2752

题意:给定一个串求出满足既是前缀又是后缀的串的起始位置

sol:又是一发next数组加深题目,很明显next数组指向的是最长的一个前缀串,所以最后一个指针指向的next就是一个最长前缀

之后从这个最长前缀末尾开始下一个指针又是前缀的最长前缀,而后缀和前缀相同,所以这个是第二长的前缀,只要递归结束即可

  1 //kmp题目shui by acvc

bubuko.com,布布扣
 2 //kmp每次都是求的最长的前缀
 3 #include<cstring>
 4 #include<algorithm>
 5 #include<cstdio>
 6 #include<vector>
 7 using namespace std;
 8 const int MAX = 400000+10;
 9 int next[MAX];
10 char str[MAX];
11 vector<int> s;
12 int main()
13 {
14     while(scanf("%s",str)!=EOF)
15     {
16         s.clear();
17         int n=strlen(str); next[0]=0,next[1]=0;
18         for(int i=1;i<n;i++)
19         {
20             int j=next[i];
21             while(j&&str[i]!=str[j]) j=next[j];
22             if(str[i]==str[j]) next[i+1]=j+1;
23             else next[i+1]=0;
24         }
25         //for(int i=0;i<=n;i++) printf("%d ",next[i]);
26     //    printf("\n");
27         int j=strlen(str);
28         while(j)
29         {
30             s.push_back(j);
31             j=next[j];
32         }
33         for(int i=s.size()-1;i>=0;i--)
34         {
35             if(i==s.size()-1) printf("%d",s[i]);
36             else printf(" %d",s[i]);
37         }
38         printf("\n");
39     }
40     return 0;
41 }
bubuko.com,布布扣

 

 poj 2185

题意:输入一个矩阵由字符组成,求出矩阵的最小组成单位。

sol:这道题没解出来,参考网上代码。其实也是一个next数组理解题目,只不过变成二维看起来比较牛x而已

我们对每行和每列分别求出其对应的周期然后对行取下最小公倍数,对列取下最小公倍数即可,当公倍数大于边界时要特判

bubuko.com,布布扣
 1 #include<iostream>
 2 #include<stdio.h>
 3 using namespace std;
 4 char s[10005][80];
 5 int subrow[10005];
 6 int subcol[80];
 7 int next[10005];
 8 int row,col;
 9 int nextrow(int r)
10 {
11     int i=0,j=-1;
12     next[0]=-1;
13     while(i<col)
14     {
15         if(j==-1||s[r][i]==s[r][j])
16         {
17             i++;j++;
18             next[i]=j;
19         }
20         else
21             j=next[j];
22     }
23     return i-next[i];
24 }
25 int nextcol(int c)
26 {
27     int i=0,j=-1;
28     next[0]=-1;
29     while(i<row)
30     {
31         if(j==-1||s[i][c]==s[j][c])
32         {
33             i++;j++;
34             next[i]=j;
35         }
36         else
37             j=next[j];
38     }
39     return i-next[i];
40 }
41 
42 int LCM(int a,int b)
43 {
44     int x=a,y=b;
45     int r=x%y;
46     while(r>0)
47     {
48         x=y;
49         y=r;
50         r=x%y;
51     }
52     return a*b/y;
53 }
54 int main()
55 {
56     while(scanf("%d%d",&row,&col)==2)
57     {
58         for(int i=0;i<row;i++)
59             scanf("%s",s[i]);
60         for(int i=0;i<row;i++)
61             subrow[i]=nextrow(i);
62         for(int i=0;i<col;i++)
63             subcol[i]=nextcol(i);
64         int x=1;
65         for(int i=0;i<row;i++)
66             x=LCM(x,subrow[i]);
67         if(x>col)
68             x=col;
69         int y=1;
70         for(int i=0;i<col;i++)
71             y=LCM(y,subcol[i]);
72         if(y>row)
73             y=row;
74         printf("%d\n",x*y);
75     }
76     return 0;
bubuko.com,布布扣

77 } 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

  

hdu poj KMP简单题目总结

原文:http://www.cnblogs.com/acvc/p/3539060.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!