• 【HDU 5510 Bazinga】字符串


    2015沈阳区域赛现场赛第2题

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5510

    题意:给定一个由字符串组成的序列,一共n个元素,每个元素是一个不超过2000个字符的字符串。求"存在秩小于 i 且不是 i 的子串"的最大的 i (1<= i <= n)。

    数据范围:n [1, 500],T组输入,T [1, 50]

    思路:从1到n-1枚举每个字符串str[i],判断是否有 j < i 使得str[j]不是str[i]的子串,若有,将 i 标记为当前最优解。枚举结束后最后标记的 i 即为所求;若始终未标记,则不存在,输出-1。

    串匹配用了KMP,对同一模式串的next数组只在需要的时候生成一遍,再次需要时直接取用。

    另外,开辟一个vis数组记录子串关系以省略一些匹配。即当判断出 str[i] 是 str[j] 的子串时(i < j), 意味着有比 i 秩更大的串 str[j] 包含了 str[i],那么只匹配str[j]就可以了,对str[i]的匹配是不必要的了,因此标记vis[i]=1以区分。

     1 #include <cstdio>
     2 #include <cstring>
     3 using namespace std;
     4 const int MAX_N = 505;
     5 const int MAX_L = 2005;
     6 
     7 int T;
     8 int n;
     9 char str[MAX_N][MAX_L];
    10 int len[MAX_N];
    11 int next[MAX_N][MAX_L];
    12 
    13 char has_cal[MAX_N];//是否已计算
    14 char vis[MAX_N];//是否存在秩更大的母串
    15 
    16 int Index_KMP(int s, int t, int pos, int next[]){
    17 //下标从1开始,[0]无意义
    18     int i=pos, j=1;
    19     char* S = str[s];
    20     char* T = str[t];
    21     while(i<=len[s] && j<=len[t]){
    22         if(j==0 || S[i]==T[j]){i++; j++;}
    23         else j=next[j];
    24     }
    25     if(j>len[t]) return i-len[t];
    26     else return 0;
    27 }
    28 
    29 void get_next(int t, int* next){
    30     int i=1, j=0;
    31     char* T = str[t];
    32     int lt = len[t];
    33     next[0] = next[1] = 0;
    34     while(i<lt){
    35         if(j==0 || T[i]==T[j]){next[++i] = ++j;}
    36         else j=next[j];
    37     }
    38 }
    39 
    40 int main()
    41 {
    42     freopen("5510.txt", "r", stdin);
    43     scanf("%d", &T);
    44     for(int ca = 1; ca<=T; ca++){
    45         
    46         scanf("%d", &n);
    47         for(int i=0; i<n; i++){
    48             scanf("%s", str[i]+1);
    49             len[i] = 0;
    50             for(int j=1; str[i][j]!=''; j++){
    51                 len[i]++;//统计串长度
    52             }
    53         }
    54         
    55         memset(vis, 0, sizeof(vis));
    56         memset(has_cal, 0, sizeof(has_cal));
    57         int flag = 0;
    58         for(int i=1; i<n; i++){ 
    59             for(int j=0; j<i; j++){
    60                 if(vis[j]) continue; //存在秩比它更大的母串,跳过此次比对
    61                 if(!has_cal[j]) {
    62                     get_next(j, next[j]);
    63                     has_cal[j] = 1;
    64                 }
    65                 //printf("%s %s
    ", str[i]+1, str[j]+1);
    66                 if(Index_KMP(i, j, 0, next[j]) == 0){
    67                     flag = i+1;
    68                     break; //i是当前最优解
    69                 }else vis[j] = 1;
    70             }
    71         }
    72         printf("Case #%d: %d
    ", ca, flag ? flag : -1);
    73     }
    74     return 0;
    75 }
  • 相关阅读:
    VANET
    OTCL,面向对象的脚本一
    NetFPGA-SUME下reference_nic测试
    Mininet-wifi安装和简单使用
    18寒假
    DistBlockNet:A Distributed Blockchains-Based Secure SDN Architecture for IOT Network
    SDVN
    Papers3
    高级软件工程实践总结
    Beta集合
  • 原文地址:https://www.cnblogs.com/helenawang/p/5487311.html
Copyright © 2020-2023  润新知