FZU 2128 最长子串
题目链接:最长子串
思路:依次找出每个子串的在字符串中的首尾地址,所有子串先按照尾地址从小到大排序。然后首地址从小到大排。
遍历一遍每个子串的首地址和它后面相邻子串的尾地址之差-1, 第一个子串的首地址,字符串长度-最后一个子串的首地址-1的最大值就是ans。
st1----------ed1
-------st2------------ed2
例如这种情况说明,可能出现的一个ans 就是 ed2和st1之间的字符个数。这时候没有ed2最后一个字符,st1第一个字符,所以不包含str1和str2.
关于找每个子串的位置,有两种方法,kmp和strstr.
会找到多少个子串位置呢,最大当然不是n,而是字符串长度!结构体数组开小,RE了一个半点~~~
kmp AC 代码:
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std; const int maxn = 1000005; struct Node {
int st, ed;
} node[maxn]; char s[maxn], t[1005][105];
int n, cnt, next[105]; bool cmp(Node a, Node b) {
if (a.ed != b.ed)
return a.ed < b.ed;
else return a.st <= b.st;
} void get_next(char p[]) {
memset(next, 0, sizeof(next));
int len = strlen(p);
int i = 0;
next[0] = -1;
int k = -1;
while(i<len) {
if (k == -1 || p[i] == p[k]) {
i++;
k++;
next[i] = k;
}
else k = next[k];
}
} void kmp(char s[], char p[]) {
int lens = strlen(s);
int lenp = strlen(p);
int i = 0, j = 0;
get_next(p); while(i<lens && j<lenp) {
if (j == -1 || s[i] == p[j]) {
i++;
j++;
}
else j = next[j];
if (j == lenp) {
node[cnt].st = i-lenp;
node[cnt].ed = i-1;
cnt++;
j = next[j];
}
}
} int main() {
while (scanf("%s", s) == 1) {
scanf("%d", &n);
for (int i = 0; i < n; i++)
scanf("%s", t[i]);
cnt = 0;
for (int i = 0; i < n; i++) {
kmp(s, t[i]);
}
sort(node, node + cnt, cmp);
int ans = -1;
for (int i=0; i<cnt-1; ++i) {
int st = node[i].st;
int ed = node[i+1].ed;
ans = max(ans, ed - st - 1);
} int len = strlen(s);
if (cnt > 0) {
ans = max(ans, node[0].ed);
ans = max(ans, len-node[cnt-1].st-1);
}
else ans = len;
printf("%d\n", ans);
}
}
strstr函数处理AC代码:
#include <stdio.h>
#include <string.h>
#include <iostream>
#include <algorithm>
using namespace std; char s[1000010], p[110];
char str[1000010]; struct Node {
int st, ed;
}node[1000010]; int next[110];
int cnt; bool cmp(Node a, Node b) {
if (a.ed != b.ed)
return a.ed < b.ed;
else return a.st <= b.st;
} bool check(char s[], char p[]) {
if (strstr(s, p))
return true;
return false;
} void solve(char s[], char p[], int pre) { // 开始没设pre 参数。这样每次找到的位置只是相对当前字符串的,不能直接设为node[cnt].st 和 node[cnt].ed.
int lenp = strlen(p);
if (check(s, p)) {
int num = strstr(s, p) - s;
node[cnt].st = num + pre;
node[cnt].ed = num + pre + lenp - 1;
cnt++;
solve(s+num+lenp, p, pre+num+lenp);
}
} int main() {
int n;
while(~scanf("%s", s)) {
cnt = 0;
scanf("%d", &n);
for (int i=0; i<n; ++i) {
scanf("%s", p);
solve(s, p, 0);
}
sort(node, node+cnt, cmp);
int ans = 0; for (int i=0; i<cnt-1; ++i) {
int st = node[i].st;
int ed = node[i+1].ed;
ans = max(ans, ed - st - 1);
}
int len = strlen(s);
if (cnt > 0) {
ans = max(ans, node[0].ed);
ans = max(ans, len-node[cnt-1].st-1);
}
else ans = len;
printf("%d\n", ans);
}
return 0;
}
后话,感觉无论是kmp还是strstr都明显会超时,如kmp是 n*strlen(str),最大是10^3*10^6。然,并没有,而且题解貌似都是这样的解........
挺好的题,会的kmp,需要思考的方案。
FZU 2128 最长子串的更多相关文章
- 福州大学第十届校赛 & fzu 2128最长子串
思路: 对于每个子串,求出 母串中 所有该子串 的 开始和结束位置,保存在 mark数组中,求完所有子串后,对mark数组按 结束位置排序,然后 用后一个的结束位置 减去 前一个的 开始 位置 再 减 ...
- Problem 2128 最长子串(kmp+strstr好题经典)
Problem 2128 最长子串 Accept: 134 Submit: 523Time Limit: 3000 mSec Memory Limit : 65536 KB Probl ...
- fzu Problem 2128 最长子串(KMP + strstr 经典好题)
Problem Description 问题很简单,给你一个字符串s,问s的子串中不包含s1,s2...sn的最长串有多长. Input 输入包含多组数据.第一行为字符串s,字符串s的长度1到10 ...
- 最长子串(FZU2128)
最长子串 Time Limit:3000MS Memory Limit:65536KB 64bit IO Format:%I64d & %I64u Submit Status ...
- [LeetCode] Longest Substring with At Most Two Distinct Characters 最多有两个不同字符的最长子串
Given a string S, find the length of the longest substring T that contains at most two distinct char ...
- POJ 3294 Life Forms 后缀数组+二分 求至少k个字符串中包含的最长子串
Life Forms Description You may have wondered why most extraterrestrial life forms resemble humans, ...
- LeetCode: 3_Longest Substring Without Repeating Characters | 求没有重复字符的最长子串的长度 | Medium
题目: Given a . For . 解题思路: 这个题让找一个字符串中具有不重复单词的最长子串的长度,如:ababc,子串为abc,长度为3.有这么几个方法: 方法一: 依赖字符串本身的一些特有函 ...
- [getLongestLength] 加和为0的最长子串长度
点击这里查看原文 假设一个数组仅仅由1和-1组成,求该数组的和为0的最长子串的长度. 例如: {1,-1,1,-1,1,1,1} 输出:4. 昨天机试的时候做到这道题,不会做,今天思考一下. 普通的解 ...
- POJ-3294-Life Forms(后缀数组-不小于 k 个字符串中的最长子串)
题意: 给定 n 个字符串,求出现在不小于 k 个字符串中的最长子串. 分析: 将 n 个字符串连起来,中间用不相同的且没有出现在字符串中的字符隔开,求后缀数组. 然后二分答案,将后缀分成若干组,判断 ...
随机推荐
- Python字典猜解
摘要 目标 使用Python破解WordPress用户密码 使用Python破解zip压缩包密码 思路 通过表单提交项构建数据包,使用字典中的可选字符进行逐一排列组合暴力破解WordPress的用户密 ...
- 2018-2019-1 20189218《Linux内核原理与分析》第五周作业
系统调用的三层机制 用户态.内核态和中断 用户态.较低的执行级别,只能访问一部分内存,只能执行一部分指令. 内核态.高级执行级别,可以访问任意物理内存,可以执行特权指令. 中断.系统从用户态进入内核态 ...
- [c/c++]指针(3)
在指针2中提到了怎么用指针申配内存,但是,指针申配的内存不会无缘无故地 被收回.很多poj上的题都是有多组数据,每次地数组大小会不同,所以要重新申请 一块内存.但是原来的内存却不会被收回,也是说2.3 ...
- 使用maven开发MR
1.安装mvn(可以省略,因为eclipse自带maven插件) 1.1. 上传安装包到linux 1.2. 解压maven安装包 mkdir /usr/maven -bin.tar.gz -C /u ...
- 在linux桌面上显示图标
把应用程序的图标添加到桌面上 左图显示了把应用程序的图标添加到桌面上的两种方法,哪种更好看? 想要把应用程序图标添加到桌面上,请先确保已设置了在桌面上显示图标,方法是: 1.安装gnome-tweak ...
- 51NOD 1117 聪明的木匠
来源:http://www.51nod.com/onlineJudge/questionCode.html#!problemId=1117 挑战原题吧 大概 每次挑选最小的两个,合起来 #inclu ...
- Unity3D学习笔记(十):Physics类和射线
物理系统:碰撞器.触发器等 力:有大小有方向的矢量,有受力点位置(和向量的区别) ----F = ma(m质量,a加速度,质量越大,加速度越小,停下来越慢) ----m1v1 = m2v2(冲量守恒定 ...
- C#学习笔记(六):循环嵌套、复杂数据类型和枚举
复杂数据类型 默认情况:0,1,2,3 赋值情况:0,3,4,5://修改初始值,后面都会改变 定义在class外面,作用域更大 定义在class里面(类种类),只能在类里使用 枚举作用:方便把不同角 ...
- NOI 16 买房子
买房子(NOI 16) 总时间限制: 1000ms 内存限制: 65536kB 描述 某程序员开始工作,年薪N万,他希望在中关村公馆买一套60平米的房子,现在价格是200万,假设房子价格以每年百分之K ...
- Linux command line exercises for NGS data processing
by Umer Zeeshan Ijaz The purpose of this tutorial is to introduce students to the frequently used to ...