……

POJ 3080 Blue Jeans、POJ 3461 Oulipo——KMP应用

题目:POJ3080 http://poj.org/problem?id=3080

题意:对于输入的文本串,输出最长的公共子串,如果长度相同,输出字典序最小的。

这题数据量很小,用暴力也是16ms,用后缀数组可以到0ms,但我不会XD。

暴力:

 1 #include<cstdio>
 2 #include<cstring>
 3 using namespace std;
 4 char str[15][65],ans[65];
 5 int main(){
 6     int T,n;  scanf("%d", &T);
 7     while (T--){
 8         memset(ans,0,sizeof(ans));
 9         scanf("%d", &n);
10         for (int i = 0; i < n; i++)  scanf("%s", str[i]);
11 
12         for (int i = 0; i < strlen(str[0]); i++)
13             for (int j = i + 2; j < strlen(str[0]); j++){
14                 char s[65];//子串
15                 strncpy(s, str[0] + i, j - i + 1);///strncpy
16                 s[j - i + 1] = '\0';
17 
18                 int flag = 1;
19                 for (int k = 1; flag && k < n; k++)
20                     if (strstr(str[k], s) == NULL)
21                         flag = 0;
22                 ///匹配成功,判长度和字典序
23                 if (flag && (j - i + 1 > strlen(ans) || (j - i + 1 == strlen(ans)&&strcmp(ans, s)>0) ) )
24                     strcpy(ans, s);
25             }
26 
27         if (strlen(ans) < 3)  puts("no significant commonalities");
28         else  puts(ans);
29     }
30     return 0;
31 }

 

KMP:

 1 #include <iostream>
 2 #include <cstdio>
 3 #include <cstring>
 4 using namespace std;
 5 char str[15][65],ans[65];
 6 int next[65];
 7 //计算串str的next数组
 8 void getnext(char *str){
 9     int len=strlen(str);
10     int j=0,k=-1;
11     next[0]=-1;
12     while(j<len){
13         if(k==-1||str[j]==str[k]) next[++j]=++k;
14         else k=next[k];
15     }
16 }
17 
18 //返回串S中第一次出现串T的开始位置
19 int KMP(char *S,char *T){
20     int l1=strlen(S), l2=strlen(T);
21     int i=0,j=0;
22     while(i<l1){
23         if(j==-1||S[i]==T[j])
24             i++, j++;
25         else j=next[j];
26         if(j==l2) return i-l2+1;
27     }
28     return -1;//若一直不匹配则返回-1
29 }
30 
31 int main(){
32     int T,n;
33     scanf("%d", &T);
34     while(T--){
35         memset(ans,0,sizeof(ans));
36         scanf("%d", &n);
37         for(int i=0;i<n;i++)  scanf("%s", str[i]);
38 
39         for(int i=0; i<strlen(str[0]); i++)//把第一个串的每一个子串当作模板串,求next数组,并和后面的每一个串去匹配
40             for(int j=i+2; j<strlen(str[0]); j++){
41                 char s[65];
42                 strncpy(s, str[0] + i, j - i + 1);///strncpy
43                 s[j - i + 1] = '\0';
44                 getnext(s);
45 
46                 int flag = 1;
47                 for(int k = 1; flag&&k < n; k++)
48                     if(KMP(str[k], s)==-1)
49                         flag = 0;
50                 ///匹配成功,判长度和字典序
51                 if(flag&& ( strlen(s)>strlen(ans) || ( strlen(s)==strlen(ans)&&strcmp(s, ans)<0)))
52                         strcpy(ans, s);
53             }
54 
55         if(strlen(ans) < 3)   puts("no significant commonalities");
56         else  puts(ans);
57     }
58     return 0;
59 }

 

 

 

题目:POJ3461 http://poj.org/problem?id=3461

题意:求第一个串在第二个串中出现的次数 

 1 //求第一个串在第二个串中出现的次数
 2 #include<iostream>
 3 #include<cstring>
 4 #include<cstdio>
 5 using namespace std;
 6 #define MAXN 1000050
 7 char s[MAXN],t[MAXN];
 8 int next[MAXN];
 9 void getnext(char *str){
10     int len=strlen(str);
11     int j=0,k=-1;
12     next[0]=-1;
13     while(j<len){
14         if(k==-1||str[j]==str[k]) next[++j]=++k;
15         else k=next[k];
16     }
17 }
18 
19 int KMP(char *S,char *T){//返回S中出现T的次数
20     int l1=strlen(S), l2=strlen(T);
21     int ans=0,i=0,j=0;
22     while(i<l1){
23         if(j==-1||S[i]==T[j])
24             i++, j++;
25         else j=next[j];
26         if(j==l2) ans++;
27     }
28     return ans;
29 }
30 int main(){
31     int T;  scanf("%d",&T);
32     while(T--){
33         scanf("%s%s",t,s);
34         getnext(t);//获得第一个串的next数组去匹配第二个串
35         printf("%d\n",KMP(s,t));
36     }
37     return 0;
38 }

 

posted @ 2019-01-31 12:12  noobimp  阅读(126)  评论(0编辑  收藏  举报