zoukankan      html  css  js  c++  java
  • 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] = '';
    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] = '';
    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
    ",KMP(s,t));
    36     }
    37     return 0;
    38 }
  • 相关阅读:
    Egret的第三方库制作,以及在大型项目中的应用
    阿里云申请免费https证书 + IIS服务器安装
    Android事件处理的2种方式:监听器与回调
    Android工具类-关于网络、状态的工具类
    Android下Notification,样式style,主题theme的功能实现
    静态工厂模式 理解
    Android下的联网下载的操作
    Android启动Activity的标准Action和标准Category
    Android RGB颜色查询对照表
    Android颜色值(RGB)所支持的四种常见形式
  • 原文地址:https://www.cnblogs.com/noobimp/p/10341435.html
Copyright © 2011-2022 走看看