【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]!=‘\0‘; 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\n", 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\n", ca, flag ? flag : -1);
73     }
74     return 0;
75 }
时间: 2024-10-12 11:53:59

【HDU 5510 Bazinga】字符串的相关文章

hdu 5510 Bazinga(字符串kmp)

Bazinga Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)Total Submission(s): 2287    Accepted Submission(s): 713 Problem Description Ladies and gentlemen, please sit up straight.Don't tilt your head. I'm serious.For

hdu 5510 Bazinga 字符串+哈希

Bazinga Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)Total Submission(s): 2078    Accepted Submission(s): 642 Problem Description Ladies and gentlemen, please sit up straight.Don't tilt your head. I'm serious.For

Hdu 5510 Bazinga(KMP+尺取法)

题目地址:http://acm.split.hdu.edu.cn/showproblem.php?pid=5510 思路:设两个指针l.r,对于字符串a.b.c,若a为b的子串则下次比较时可直接比较b,c.枚举r,依次比较s[l]--s[r-1]是否为s[r]的子串,若s[i]为s[r]的子串,则l++.否则答案更新为r. #include<cstdio> #include<cstring> #include<iostream> #include<algorith

hdu 5510 Bazinga (KMP+暴力标记)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5510 思路: 一开始直接用KMP莽了发,超时了,后面发现如果前面的字符串被后面的字符串包含,那么我们就不需要用前面的字符串去比较了,把他标记掉就好了. 实现代码: #include<iostream> #include<algorithm> #include<cstring> #include<cstdio> using namespace std; char

HDU 5510 Bazinga(KMP)

Bazinga Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)Total Submission(s): 4572    Accepted Submission(s): 1459 Problem Description Ladies and gentlemen, please sit up straight. Don't tilt your head. I'm serious.F

HDU 5510 Bazinga (KMP)

题意:给定 n 个 字符串,让你找出最大的 r,使得存在一个 sl 不是sr的子串(l  < r). 析:KMP算法,不过直接暴力就别想了,肯定TLE,所以我们考虑一下,用两个指针 l, r,如果sl 不是 sr的字串,那么们就可以更新r,继续往后,直到找到最后. 代码如下: #pragma comment(linker, "/STACK:1024000000,1024000000") #include <cstdio> #include <string>

hdu 5510 Bazinga(暴力)

Problem Description Ladies and gentlemen, please sit up straight. Don't tilt your head. I'm serious. For n given strings S1,S2,?,Sn, labelled from 1 to n, you should find the largest i (1≤i≤n) such that there exists an integer j (1≤j<i) and Sj is not

hdu 5510 Bazinga (kmp+dfs剪枝) 2015ACM/ICPC亚洲区沈阳站-重现赛(感谢东北大学)

废话: 这道题很是花了我一番功夫.首先,我不会kmp算法,还专门学了一下这个算法.其次,即使会用kmp,但是如果暴力枚举的话,还是毫无疑问会爆掉.因此在dfs的基础上加上两次剪枝解决了这道题. 题意: 我没有读题,只是队友给我解释了题意,然后我根据题意写的题. 大概意思是给n个字符串,从上到下依次标记为1——n,寻找一个标记最大的串,要求这个串满足:标记比它小的串中至少有一个不是它的子串. 输入: 第一行输入一个整型t,表示共有t组数据. 每组数据首行一个整型n,表示有n个串. 接下来n行,每行

HDU 5510 Bazinga (字符串匹配)

题目:传送门. 题意:t 组数据,每组 n 个串,对于第 i 个串如果存在 1 到 i-1 中的某个串不是 i 的子串,那么这个第 i 个串符合题意,求 i 的最大值. 题解:KMP,AC自动机也可以,直接匹配就行.注意如果串 j 是j+1的子串,那么对于j+2来说只需要匹配j+1是不是他的子串即可,因为比匹配 j 更容易符合题意.用cin会超时,要用scanf. #include <iostream> #include <cstdio> #include <cmath>